快速幂
int pow(int a, int k) {
int ans = 1;
while(k) {
if(k &1) ans *= a; //判断奇偶只用判断最后一位比取模快
a *= a;
k >>=1; //右移一位,即缩小一倍,比除法快多了
}
return ans;
}
快速幂求模
如果超过计算机的取值范围了,那么快速取模的数可以是很大很大的数,因此需要进行取模。
由以上算法可以,最终的幂值就是各个值相乘,其中的某个乘式取模和算出整个值取模效果是一样的,效率更高。
int pow_mod(int a, int k,int mod) {
int ans = 1%mod;
while(k) {
if(k &1) ans =(long long) ans*a%mod; ////为了使数字不会超过最大值,所以每次都取模
a = (long long)a*a%mod;
k >>=1; //右移一位,即缩小一倍,比除法快多了
}
return ans;
}
取模解释:
//2^n = 13 ,拆分成 13 = 1 + 4 + 8,即 2^13 = 2^1 * 2^4 * 2^8。
//所以在下面两处取模对结果没有影响。
//取模,防止进行稍微大点的数运算时超过取值范围。
例题:
BZOJ1008 越狱 组合数学
Description
监狱有连续编号为1…N的N个房间,每个房间关押一个犯人,有M种宗教,每个犯人可能信仰其中一种。如果相邻房间的犯人的宗教相同,就可能发生越狱,求有多少种状态可能发生越狱
Input
输入两个整数M,N.1<=M<=108,1<=N<=1012
Output
可能越狱的状态数,模100003取余
Sample Input
2 3
Sample Output
6
HINT
6种状态为(000)(001)(011)(100)(110)(111)
n个房间 m种宗教,总状态数即m^n
若不越狱,即相邻房间的两个人宗教不同,所以第一个人有m种选择,
则后面的每一个人都有m-1种选择,
所以不越狱的状态总数等于m(m-1)^(n-1);
所以越狱的状态数就为m^n -m(m-1)^(n-1)。
解决了这个问题后,快速幂解决就好了。
#include<cstdio>
#define mod 100003
#define ll long long
using namespace std;
ll m,n;
ll qpow(ll a,ll b)
{
ll c=1,d=a%mod;
while (b>0)
{
if (b&1)
c=((c%mod)*(d%mod))%mod;
b>>=1;
d=((d%mod)*(d%mod))%mod;
}
return c;
}
int main()
{
scanf("%lld%lld",&m,&n);
long long ans=qpow(m,n);
ans=ans-m*qpow(m-1,n-1)%mod;
if (ans<0) ans+=mod;
printf("%lld",ans);
return 0;
}