一直对那些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,这一次我真得领教了怎么两种语言输入处理速度的差别了,不能小看测试数据的量啊。