HDU 1420 蒙哥马利幂模算法
Prepared for New Acmer
蒙哥马利幂模思想:
在幂模运算中,通常是用幂模运算转换为乘模运算。有以下两个公式:
1)a*b%n=(a%n)*(b%n)%n
2)(a+b)%n=(a%n+b%n)%n
当我们计算D=C^15%N时,有:
C1=C*C%N=C^2%N
C2=C1*C%N=C^3%N
C3=C2*C2%N=C^6%N
C4=C3*C%N=C^7%N
C5=C4*C4%N=C^14%N
C6=C5*C%N=C^15%N
所以,幂模运算可以转化为乘模运算。继续看,我们会发现,要求D=C^E%N,要知道E何时能整除2,并不需要反复进行减一或者除二的操作,只需要验证E的二进制个位是0还是1就行了。
本题代码:#include <cstdio> __int64 fun(__int64 A,__int64 B,__int64 C) { __int64 k = 1; A%=C; while(B>=1) { if((B&1)!=0) k = (k*A)%C; B>>= 1; A = A*A%C; } return k; } int main(int argc, char *argv[]) { int n; scanf("%d",&n); __int64 A,B,C; while(n--) { scanf("%I64d%I64d%I64d",&A,&B,&C); printf("%I64d\n",fun(A,B,C)); } return 0; }
普通代码:
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <cmath> #include <string> #include <iomanip> using namespace std; int main(int argc, char *argv[]) { int n; scanf("%d",&n); int A,B,C; while(n--) { scanf("%d%d%d",&A,&B,&C); __int64 ans = 1; for(int i = 1; i <= B; i++) { ans*=A; ans%=C; //注意要求余,不然很容易数据溢出; } printf("%I64d\n",ans); } return 0; }