標籤:style blog http os io strong for ar
部落格原文地址:http://blog.csdn.net/xuechelingxiao/article/details/38614491
對於一般的求a^b%c的值,當a,b都在long long範圍內,c在1e9的時候,都可以用快速冪模數進行求解。
LL powerMod(LL x, LL k, LL m){ LL res = 1; while(x %= m, k){ if(k&1) res *= x, res %= m; x *= x, k >>=1; } return res;}
但是當其中的參數變得相對大之後,單純的快速冪可能就不能解決問題了,下面這兩個題就是當a^b%c中某個參數變大之後出現的問題。
FOJ 1752 A^B mod C
題目大意:題意很簡單,就是求a^b%c的結果,只是a,b,c的範圍是 (1<=a,b,c<2^63)。
思路:這個題最關鍵的問題是在快速冪的時候,由於a的最大值是2^63-1,所以會出現乘法溢出,這也是最容易WA的地方。
要解決這個問題,就需要將乘法轉換成加法,進行“快速乘”(暫且這麼叫吧,我也不知道叫啥-。-),就是代碼中的multiplyMod,接下來就沒什麼問題了。
#include <stdio.h>#include <iostream>#define ULL long longusing namespace std;ULL n, m, mod;ULL multiplyMod(ULL x, ULL k, ULL m){ ULL res = 0; x %= m; while(k){ if(k&1){ res += x; if(res >= m) res -= m; } x += x; if(x >= m){ x -= m; } k >>=1; } return res;}ULL powerMod(ULL x, ULL k, ULL m){ ULL res = 1; while(k){ if(k&1){ res = multiplyMod(res, x, m); } x = multiplyMod(x, x, m), k >>=1; } return res;}int main(){ while(~scanf("%I64d%I64d%I64d", &n, &m, &mod)){ printf("%I64d\n", powerMod(n, m, mod)); } return 0;}
FOJ 1759 Super A^B mod C
題目大意:一樣的求a^b%c的結果,只是b的範圍變得很大了, (1<=A,C<=1000000000,1<=B<=10^1000000)。
思路:對於這個問題,就需要用到一個公式
A^x = A^(x % Phi(C) + Phi(C)) (mod C)
對於這個公式,可以給出兩個證明的部落格,一個是aekdycoin大犇的證明:http://www.narutoacm.com/archives/a-pow-b-mod-m/
另一個是 http://www.narutoacm.com/archives/a-pow-b-mod-m/
有了理論支援,這個題也就不是什麼問題了,代碼如下。
#include <stdio.h>#include <string.h>#define LL long longint eular(int n){int ret = 1;for(int i = 2; i*i <= n;i++)if(n%i == 0){n /= i, ret *= i-1;while(n%i == 0)n /= i, ret *= i;}if(n > 1)ret *= n-1;return ret;}LL powerMod(LL x, LL k, LL m){ LL res = 1; while(x %= m, k){ if(k&1) res *= x, res %= m; x *= x, k >>=1; } return res;}LL n, mod;char m[1000005];int main(){ while(~scanf("%I64d%s%I64d", &n, m, &mod)){ LL phi = eular(mod); int len = strlen(m); LL num = 0; for(int i = 0; i < len; ++i){ if(len >= 10){ num = (num*10+(m[i]-'0'))%phi + phi; } else { num = num*10+(m[i]-'0'); } } printf("%I64d\n", powerMod(n, num, mod)); } return 0;}