4:整数模
-
总时间限制:
- 5000ms 内存限制:
- 32768kB
-
描述
-
a除以m的余数称为a对于m的模。求ap对于m的模。
输入
- 输入数据中含有一些数据组,每个数据组含有a、p、m(0<a,p<2^32,1≤m<2^16)三个整数。若三个数都为0,则输入结束。 输出
- 针对每组a,p,m,以一行的形式输出ap对于m的模。 样例输入
-
3 18132 170 0 0
样例输出
-
13
-
-
-
解析:
-
-
对大整数求余数一般是在对其进行所有加减和乘运算时就求模。
a mod m表示a对于m的模。 那么a^p mod m = [ a^(p-1) mod m * a ] mod m 也就是可以求 a mod m = t然后求 (t * a)mod m =t ,反复
-
代码如下:
-
#include<cstdio> #include<iostream> #include<cmath> using namespace std; int main() { long long int a,p,m; while(cin>>a>>p>>m && a!=0 && p!=0 && m!=0) { long long int r=1,n; for(int i=1;i<=p;i++) { r=(r*a)%m; } cout<<r<<endl; } }
但是,依旧不是最好的方法 -
更好的用幂取模算法,若p是偶数,a^p mod m =[ a^(p/2) mod m ] ^2 mod m这可以每次把问题的规模降一倍。递归实现幂取模
-
#include<cstdio> #include<cmath> #include<iostream> using namespace std; long long qiuyu(long long di,long long zhi,long long mod); int main() { long long a,p,m,r; while(cin>>a>>p>>m && a!=0 && p!=0 && m!=0) { if(m!=1) { r=qiuyu(a,p,m); cout<<r<<endl; } else //注意若除以的余数是一,那么大整数永远是大整数,所有表示不出来,输出0 cout<<0<<endl; } } long long qiuyu(long long di,long long zhi,long long m) { long long sum; if(zhi==1) { return di%m; } else { sum=pow(qiuyu(di,zhi/2,m),2); //要注意当指数为奇数时,对其除二会使其指数少一, //所以递归玩之后要将得到的结果乘上一个底数 if(zhi%2 == 1) { di=di%m; //di有可能太大要进行求余 sum=(sum*di)%m; //结果进行乘底数操作,因为所有进行了加减乘的地方都要进行求余 } sum=sum%m; //在对新结果求余 return sum; } }