a^b%c 的三种形式

来源:互联网 发布:大数据的定义及特点 编辑:程序博客网 时间:2024/05/21 09:53

求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 20using namespace std;const int maxn = 110;// a*b%cLL 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%cLL 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\n",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 20using 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] = '\0';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\n",ans);}return 0;}



0 0