Part 1 快速幂
朴素的O(n)算法过慢,又存不下过大的变量,所以考虑将指数二进制化,每次右移一位,底数随着自乘,就有了O(logn)的算法。
大数通常需要结果对P取模, 为了避免中间变量溢出,我们可以边取模边计算,有如下等式:
(a*b)%p=((a%p)*(b%p))%p
代码如下:
#include<iostream> using namespace std; long long b, p, k; long long quick_power(long long a, long long b, long long c) { long long res = 1; a %= c; while (b != 0) { if (b & 1)res = res*a%c; b = b >> 1; a = a*a%c; } return res; } int main() { cin >> b >> p >> k; cout << b << "^" << p << " mod " << k << "=" << quick_power(b, p, k); return 0; }
Part 2 矩阵快速幂
在矩阵快速幂之前,我们需要先了解下矩阵乘法:https://en.wikipedia.org/wiki/Matrix_multiplication
与快速幂类似,再重载结构体的乘号即可。
代码如下:
#include<iostream> #include<cstdio> #include<cstring> #define maxn 101 using namespace std; typedef long long ll; const ll p=1000000007; ll N,k; struct matrix{ ll a[maxn][maxn]; matrix(){memset(a,0,sizeof(a));} matrix operator *(matrix b) { matrix ret; for(int i=1;i<=N;++i) for(int j=1;j<=N;++j) for(int k=1;k<=N;++k) ret.a[i][j]=(ret.a[i][j]+(a[i][k]*b.a[k][j])%p)%p; return ret; } void print() { for(int i=1;i<=N;++i){ for(int j=1;j<=N;++j) printf("%d ",a[i][j]); putchar('\n'); } } }; matrix quick_power(matrix b,ll k) { matrix ans; for(int i=1;i<=N;++i) for(int j=1;j<=N;++j) ans.a[i][j]=(i==j)?1:0; while(k){ if(k&1)ans=ans*b; k>>=1; b=b*b; } return ans; } int main() { scanf("%lld%lld",&N,&k); matrix bs; for(int i=1;i<=N;++i) for(int j=1;j<=N;++j) scanf("%d",&bs.a[i][j]); matrix res=quick_power(bs,k); res=res%p; res.print(); return 0; }