取模

 

取模

 

Time Limit:   1000MS       Memory Limit:   65535KB
Submissions:   571       Accepted:   96

 

Description

给你三个数X(1<=X<=10^100)、Y(1<=Y<=10^8)、Z(1<=Z<=10^4),你能计算出X^Y%Z的值吗?

Input

输入三个如上所描述的数X、Y、Z。多组输入。

Output

输出X^Y%Z的值。

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;
}

 

 

 

posted on 2012-05-24 15:37  即为将军  阅读(838)  评论(0)    收藏  举报

导航