取模
取模
Time Limit: 1000MS | Memory Limit: 65535KB |
Submissions: 571 | Accepted: 96 |
Sample Input
2 3 5 12345 2345 345 123456789123456789 19234321 2341
Sample Output
3 240 1825
【分析】
这里的用同余幂的思想
求出同余幂bn mod m,其中b,n,m都是比较大的整数。例如取b=12345678,n=456789,直接计算显然是不可行的,可以把n按二进制展开,则n=456789就变成了1101111100001010101,这样每次只需要求b mod m,b2 mod m,... b2^(k-1) mod m,然后把对应位置上的二进制是1的项乘起来,每次乘完后求除m的余数即可,大大降低了计算的复杂度。
伪代码如下:
这里还要用一些同余定理
(a+b)mod m=((a mod m)+(b mod m))mod m;
a*b mod m=(a mod m)*(b mod m) mod m;
a^b mod m=(a mod m)^b mod m;
这里解释一下代码中的第一个while循环,就是得到b对m取余的结果,即算法中的power。由于b为数组,而且没有可以存下b的变量,就用这种方法
那这种方法为什么可以呢?其实用小学学的两数相除的方法,就很容易理解了,如下:
由上图可看出,如果power大于999(随便假设的)的话,就结束里面一个while循环,这时取一次余,得到power=61;接着又进入循环,得到619后,再取一次余,得到power=107.可见,直接将b对m取余得到的数和b一部分一部分对b取余得到的最后的数是一样的。
# include<iostream> # include<cstring> using namespace std; int main() { char b[200]; unsigned long int n,m,x,i,power; int len; while(cin>>b>>n>>m) { len=strlen(b); i=0; power=0; while(i<len) { while(power<9999999&&i<len) { power=10*power+b[i]-'0'; i++; } power%=m; } x=1; while(n>0) { if(n&1) x=(x*power)%m; power=(power*power)%m; n>>=1;//得到如上的k } cout<<x<<endl; } return 0; }