JOJ1600 Big Mod

一直对那些ACM的神牛们从心底里有膜拜知情,总会对自己有些鄙视啊,好多数学方面的知识真的不是一般的匮乏,就唠叨到这里吧,

1600 : Big Mod

Result TIME Limit MEMORY Limit Run Times AC Times JUDGE
3s 8192K 1725 324 Standard

Calculate

 

 

for large values of B , P , and M using an efficient algorithm. (That's right, this problem has a time dependency !!!.)

Input

Three integer values (in the order B , P , M ) will be read one number per line. B and P are integers in the range 0 to 2147483647 inclusive. M is an integer in the range 1 to 46340 inclusive.

Output

The result of the computation. A single integer.

Sample Input

 

3
18132
17

17
1765
3

2374859
3029382
36123

Sample Output

 

13
2
13195
思路:这就是幂取模算法。

利用一个很基础的数论公式(a*b)%m=(a%m)*(b%m)%m=((a%m)*b%m)和一个指数运算法则a^(b+c)=a^b*a^c;

对于(a^p)%m;

我们可以把p写成二进制形式b0,b1,b2,b3.....bn(从低位到高位);

其对应的二进制位上相应权值为2^0,2^1,2^2,2^3,2^4,2^5,2^6,2^7,2^8.....(设为w0,w1,w2,w3,w4.....wn...).

可以想到a^p=a^(b0*w0+b1*w1+b2*w2+bn*wn)=a^(b0*w0)*a^(b1*w1)*a^(b2*w2)*......*a^(bn*wn);

我们设一个变量res来保存运算结果,并初始化为1。

现在我们从左向右遍历b的二进制序列。


如果相应的位数上对应值为1则进行:

res=(res*a)%m; //别忘了%m,这里a相当于各位对应的权值,这样做并不会影响最终的结果,因为我们有前面提到的公式。

不论相应位上是不是1都要对a进行。

a=(a*a)%m; //这样做是为了使a等于上各个二进制位对应的权值。同样别忘了%m操作。

当遍历完二进制序列后,输出res即可。

注意一点就是当b=0并且m=1的时候,要特殊考虑(当然也可以不用),完全取决于你的程序具体实现,与算法无关。

忘记说了这个算法复杂度是O(log2(n))。

下面给出上面这道题的AC代码,不知道0.03s的牛们是怎么做的。还要感谢飞哥对我的算法讲解。
刚刚知道了0.03s的牛们是怎么做的了,原来输入输出全是标准C,这一次我真得领教了怎么两种语言输入处理速度的差别了,不能小看测试数据的量啊。
<textarea cols="50" rows="15" name="code" class="cpp:showcolumns">/* *JackyZheng *2010/12/3 *C */ #include&lt;stdio.h&gt; int main() { int a,b,m; while(scanf(&quot;%d%d%d&quot;,&amp;a,&amp;b,&amp;m)!=EOF) { a%=m; int res=1; if(b==0&amp;&amp;m==1) { printf(&quot;0/n&quot;); continue; } else { while(b) { if(b%2==1) res *= a, res %= m; a *= a, a %= m; b&gt;&gt;=1; } printf(&quot;%d/n&quot;,res); } } }</textarea>

你可能感兴趣的:(算法,测试,Integer,input,语言,output)