首先储备知识:数的快速幂
参考资料:http://blog.csdn.net/y990041769/article/details/22311889
快速幂取模
用法:用于求解 a 的 b 次方,而b是一个非常大的数,用O(n)的复杂度会超时。
那么就需要这个算法,注意它不但可以对数求次幂,而且可用于矩阵快速幂。
假如求 x ^ n 次方
我们可以把 n 表示为 2^k1 + 2k2 + 2^k3....,可以证明所有数都可以用前式来表示。(其实就是二进制表示数的原理)
那么 x^n = x^2^k1 * x^2^k2 * x^2^k3......
那么就可以利用二进制来加快计算速度了。
假如 x^22 , 22转化为二进制为 10110, 即 x^22 = x^16 * x^4 * x^2;
那么是不是可以在O(logn)的复杂度求解。
int fun(int x,int n) { int res=1; while(n>0) { if(n&1) res=(res*x)%p; x=(x*x)%p; n>>=1; } return res; }
关于矩阵:http://blog.csdn.net/poem_of_sunshine/article/details/21319417
与数相同,如果把数变成一个很大的矩阵,情况又是怎么样呢
首先要写出矩阵的乘法,然后把底数的部分改成一个矩阵
代码:
typedef vector<int>vec; typedef vector<vec>mat; mat mul(mat a,mat b)//矩阵的乘法 { mat c(a.size(),vec(b[0].size())); for(int i=0;i<a.size();i++) { for(int k=0;k<b.size();k++) { for(int j=0;j<b[0].size();j++) { c[i][j]=(c[i][j]+a[i][k]*b[k][j])%N; } } } return c; } mat get_ans(mat a,int n)//矩阵的快速幂 { mat b(a.size(),vec(a.size())); for(int i=0;i<a.size();i++) { b[i][i]=1; } while(n>0) { if(n&1) b=mul(b,a); a=mul(a,a); n>>=1; } return b; }