FOJ 1752 && FOJ 1759 (a^b%c 的不同情况)

博客原文地址:http://blog.csdn.net/xuechelingxiao/article/details/38614491


对于一般的求a^b%c的值,当a,b都在long long范围内,c在1e9的时候,都可以用快速幂取模进行求解。

 

1 LL powerMod(LL x, LL k, LL m){
2     LL res = 1;
3     while(x %= m, k){
4         if(k&1) res *= x, res %= m;
5         x *= x, k >>=1;
6     }
7     return res;
8 }
快速幂取模

 

但是当其中的参数变得相对大之后,单纯的快速幂可能就不能解决问题了,下面这两个题就是当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,接下来就没什么问题了。

 

 1 #include <stdio.h>
 2 #include <iostream>
 3 #define ULL long long
 4 using namespace std;
 5 
 6 ULL n, m, mod;
 7 
 8 ULL multiplyMod(ULL x, ULL k, ULL m){
 9     ULL res = 0;
10     x %= m;
11     while(k){
12         if(k&1){
13             res += x;
14             if(res >= m)
15                 res -= m;
16         }
17         x += x;
18         if(x >= m){
19             x -= m;
20         }
21         k >>=1;
22     }
23     return res;
24 }
25 
26 ULL powerMod(ULL x, ULL k, ULL m){
27     ULL res = 1;
28     while(k){
29         if(k&1){
30             res = multiplyMod(res, x, m);
31         }
32         x = multiplyMod(x, x, m), k >>=1;
33     }
34     return res;
35 }
36 
37 int main()
38 {
39     while(~scanf("%I64d%I64d%I64d", &n, &m, &mod)){
40         printf("%I64d\n", powerMod(n, m, mod));
41     }
42 
43     return 0;
44 }
FOJ 1752

 

 

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/

 

有了理论支持,这个题也就不是什么问题了,代码如下。

 

 1 #include <stdio.h>
 2 #include <string.h>
 3 #define LL long long
 4 
 5 int eular(int n){
 6     int ret = 1;
 7     for(int i = 2; i*i <= n;i++)
 8         if(n%i == 0){
 9             n /= i, ret *= i-1;
10             while(n%i == 0)
11                 n /= i, ret *= i;
12         }
13     if(n > 1)
14         ret *= n-1;
15     return ret;
16 }
17 
18 LL powerMod(LL x, LL k, LL m){
19     LL res = 1;
20     while(x %= m, k){
21         if(k&1) res *= x, res %= m;
22         x *= x, k >>=1;
23     }
24     return res;
25 }
26 
27 LL n, mod;
28 char m[1000005];
29 
30 int main()
31 {
32     while(~scanf("%I64d%s%I64d", &n, m, &mod)){
33         LL phi = eular(mod);
34         int len = strlen(m);
35         LL num = 0;
36         for(int i = 0; i < len; ++i){
37             if(len >= 10){
38                 num = (num*10+(m[i]-'0'))%phi + phi;
39             }
40             else {
41                 num = num*10+(m[i]-'0');
42             }
43         }
44         printf("%I64d\n", powerMod(n, num, mod));
45     }
46 
47     return 0;
48 }
FOJ 1759

 

posted @ 2014-08-16 16:52  GLSilence  阅读(191)  评论(0编辑  收藏  举报