• a^b%c 的三种形式


    求a^b%c,(1  <= a,b <= 2^62, 1 <= c <= 10^9)

    最主要的高速幂

    _LL mod_exp(_LL a, _LL b, int c)
    {
        _LL ans = 1;
        _LL t = a%c;
    
        while(b)
        {
            if(b&1)
                ans = ans*t%c;
            t = t*t%c;
            b >>= 1;
        }
        return ans;
    }



    求a^b%c,(1 <= a,b,c <= 2^62)

    由于c在long long范围内,中间两个long long 相乘的时候会超long long。所以对乘法再写一个高速乘法的函数,将乘法变为加法,每加一次就进行取模,就不会超long long了。

    #include <stdio.h>
    #include <iostream>
    #include <map>
    #include <set>
    #include <list>
    #include <stack>
    #include <vector>
    #include <math.h>
    #include <string.h>
    #include <queue>
    #include <string>
    #include <stdlib.h>
    #include <algorithm>
    #define LL long long
    #define _LL __int64
    #define eps 1e-12
    #define PI acos(-1.0)
    #define C 240
    #define S 20
    using namespace std;
    const int maxn = 110;
    
    // a*b%c
    LL mul_mod(LL a, LL b, LL c)
    {
    	LL ans = 0;
    	a %= n;
    	b %= n;
    	while(b)
    	{
    		if(b&1)
    		{
    			ans = ans+a;
    			if(ans >= c) ans -= c;
    		}
    		a <<= 1;
    		if(a >= c)
    			a -= c;
    		b >>= 1;
    	}
    	return ans;
    }
    //a^b%c
    LL pow_mod(LL a, LL b, LL c)
    {
    	LL ans = 1;
    	a = a%c;
    	while(b)
    	{
    		if(b&1)
    			ans = mul_mod(ans,a,c);
    		a = mul_mod(a,a,c);
    		b >>= 1;
    	}
    	return ans;
    }
    int main()
    {
    	LL a,b,c;
    	while(~scanf("%lld %lld %lld",&a,&b,&c))
    	{
    		LL ans = pow_mod(a,b,c);
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }


    求a^b%c (1 <= a,c <= 10^9, 1 <= b <= 10^1000000)

    b相当大,高速幂超时。

    有一个定理: a^b%c = a^(b%phi[c]+phi[c])%c,当中要满足b >= phi[c]。这样将b变为long long范围内的数,再进行高速幂。至于这个定理为什么成立,如今明确一点。这篇讲的挺具体:http://www.narutoacm.com/archives/a-pow-b-mod-m/

    http://acm.fzu.edu.cn/problem.php?pid=1759


    #include <stdio.h>
    #include <iostream>
    #include <map>
    #include <set>
    #include <list>
    #include <stack>
    #include <vector>
    #include <math.h>
    #include <string.h>
    #include <queue>
    #include <string>
    #include <stdlib.h>
    #include <algorithm>
    #define LL long long
    #define _LL __int64
    #define eps 1e-12
    #define PI acos(-1.0)
    #define C 240
    #define S 20
    using namespace std;
    const int maxn = 110;
    
    LL a,c,cc;
    char b[1000010];
    
    LL Eular(LL num)
    {
    	LL res = num;
    	for(int i = 2; i*i <= num; i++)
    	{
    		if(num%i == 0)
    		{
    			res -= res/i;
    			while(num%i == 0)
    				num /= i;
    		}
    	}
    	if(num > 1)
    		res -= res/num;
    	return res;
    }
    
    bool Comper(char s[], LL num)
    {
    	char bit[30];
    	int len2 = 0,len1;
    	while(num)
    	{
    		bit[len2++] = num%10;
    		num = num/10;
    	}
    	bit[len2] = '';
    
    	len1 = strlen(s);
    	if(len1 > len2)
    		return true;
    	else if(len1 < len2)
    		return false;
    	else
    	{
    		for(int i = 0; i < len1; i++)
    		{
    			if(s[i] < bit[len1-i-1])
    				return false;
    		}
    		return true;
    	}
    }
    
    //对大整数取模,一位一位的取。
    LL Mod(char s[], LL num)
    {
    	int len = strlen(s);
    	LL ans = 0;
    	for(int i = 0; i < len; i++)
    	{
    		ans = (ans*10 + s[i]-'0')%num;
    	}
    	return ans;
    }
    
    LL Pow(LL a, LL b, LL c)
    {
    	LL ans = 1;
    	a = a%c;
    	while(b)
    	{
    		if(b&1)
    			ans = ans*a%c;
    		a = a*a%c;
    		b >>= 1;
    	}
    	return ans;
    }
    
    int main()
    {
    	while(~scanf("%lld %s %lld",&a,b,&c))
    	{
    		LL phi_c = Eular(c);
    		LL ans;
    		if(Comper(b,phi_c)) // b >= phi[c]
    		{
    			cc = Mod(b,phi_c)+phi_c;
    			ans = Pow(a,cc,c);
    		}
    		else
    		{
    			int len = strlen(b);
    			cc = 0;
    			for(int i = 0; i < len; i++)
    				cc = cc*10 + b[i]-'0';
    			ans = Pow(a,cc,c);
    		}
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
    
    



  • 相关阅读:
    1. 第一章: Python基础语法
    6. 第二章:C#委托和事件之.net framework3.5委托扩展
    5. 第二章:C#委托和事件之事件
    4. 第二章:C#委托和事件之委托
    3. 第一章:C#面向对象编程之继承和多态
    2. 第一章:C#面向对象编程之抽象和封装
    1. 序言
    Xamarin.Forms 调用腾讯地图
    全国行政区划数据大放送——包含邮政编码-电话区号-简拼-区划路径
    【记录】自定义服务器验证控件
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/4553109.html
Copyright © 2020-2023  润新知