动机
为什么突然想写这个,是因为看到了POJ上的2109这道题,第一反应就是用快速幂来解题,但是自己还是不会(怪你赛后不总结查缺补漏),于是赶紧去百度查了查快速幂和对大数的取模算法,先把代码贴上来
代码
快速幂
基本原理请参见递归形式的代码
快速幂的非递归形式
long long int mi(long long int a,int b){
long long int sum = 1; //存一下当b为奇数时多出来的那一个a
while(b){
if(b&1)sum*=a; //当b为奇数时把多出来的一个a乘进去
b>>=1; //对b/2,奇数自动向下取整
a*=a; //因为a^4==(a^2)^2,所以更新a
}
return sum;
}
快速幂的递归形式
long long int mi(int a,int b){
if(b==0)return 1;
if(b&1)return a*mi(a,b-1);
else return mi(a,b/2)*mi(a,b/2);
}
快速幂取模
这里涉及的原理除了快速幂之外,还涉及到我现在数学没学到的一个定理:多个数的积取余的余数等于每个数取余的余数的积再一次取余得到的余数
换成代码表示就是(a*b*c)%m==((a%m)*(b%m)*(c%m))%m
怎么证明请自行百度@滑稽
快速幂取模的递归形式
long long int mi(int a,int b,int m) {
if(m==1)return 0;
if (b == 0)return 1;
if (b & 1) return a%m*mi(a,b-1,m)%m;
else return mi(a,b/2,m)*mi(a,b/2,m)%m;
}
快速幂取模的非递归形式
long long int mi(long long int a,int b,int m) {
long long int sum = 1;
while(b){
if(b&1)sum*=(a%m);
b>>=1;
a = (a*a)%m;
}
return sum%m;
}
后话
因为看discuss那边的说法好像是数据有问题,所以2109就没继续看下去,但是学到了东西还是蛮好的