对n<=30(其实可以100)大小的矩阵A求A^1+A^2+……+A^K,K<=1e9,A中的数%m。
从K的二进制位入手。K分解二进制,比如10110,令F[i]=A^1+A^2+……+A^(2^i),那么答案就是F[10000]*A^110+F[100]*A^10+F[10]+A^0。也就是说如果知道F就可以得答案。
F亦可递推,F[i]=F[i-1]*(A^(2^i-1)+A^0)。完美!什么log方,都是假的!
1 #include<stdio.h> 2 #include<string.h> 3 #include<algorithm> 4 #include<math.h> 5 //#include<iostream> 6 using namespace std; 7 8 int n,K,mod; 9 #define maxn 111 10 #define LL long long 11 typedef LL mat[maxn][maxn]; 12 mat f,a,last,tmp,t,ans,E; 13 void init(mat &a) 14 { 15 memset(a,0,sizeof(a)); 16 for (int i=1;i<=n;i++) a[i][i]=1; 17 } 18 void add(mat a,mat b,mat &ans) 19 { 20 for (int i=1;i<=n;i++) 21 for (int j=1;j<=n;j++) 22 ans[i][j]=(a[i][j]+b[i][j])%mod; 23 } 24 void mul(mat a,mat b,mat &ans) 25 { 26 mat t; 27 memset(t,0,sizeof(t)); 28 for (int i=1;i<=n;i++) 29 for (int j=1;j<=n;j++) 30 for (int k=1;k<=n;k++) 31 t[i][j]=(t[i][j]+a[i][k]*b[k][j]%mod)%mod; 32 for (int i=1;i<=n;i++) 33 for (int j=1;j<=n;j++) 34 ans[i][j]=t[i][j]; 35 } 36 int main() 37 { 38 scanf("%d%d%d",&n,&K,&mod); 39 for (int i=1;i<=n;i++) 40 for (int j=1;j<=n;j++) 41 scanf("%lld",&a[i][j]),tmp[i][j]=f[i][j]=a[i][j]; 42 init(last);init(E); 43 memset(ans,0,sizeof(ans)); 44 while (K) 45 { 46 if (K&1) 47 { 48 mul(f,last,t); 49 add(ans,t,ans); 50 mul(last,tmp,last); 51 } 52 add(tmp,E,t); 53 mul(f,t,f); 54 mul(tmp,tmp,tmp); 55 K>>=1; 56 } 57 for (int i=1;i<=n;i++) 58 { 59 for (int j=1;j<=n;j++) 60 printf("%lld ",ans[i][j]); 61 puts(""); 62 } 63 return 0; 64 }