题目链接:https://vjudge.net/problem/LightOJ-1132
题目意思:(1K + 2K + 3K + ... + NK) % 232
矩阵快速幂的题目一般都很短,这道题也一样就是这么简单。
思路:运用到了组合数a^k=C(k,0)*a^k+C(k,1)*a^(k-1)+C(k,2)*a^(k-2)+C(k,3)*a^(k-3)+C(k,4)*a^(k-4)+……C(k,k)*a^(k-k),运用这个式子我们可以构造以下矩阵。
1 C(k,0), C(k,1), C(k,2), C(k,3)………… …… C(k,k) 0 (n-1)^k (n)^k 2 C(k-1,0), C(k-1,1), C(k-1,2), C(k-1,3)…………C(k-1,k-1) 0 (n-1)^(k-1) (n)^(k-1) 3 C(k-2,0), C(k-2,1), C(k-2,2), C(k-2,3)…………C(k-2,k-2) 0 (n-1)^(k-2) (n)^(k-2) 4 C(k-3,0), C(k-3,1), C(k-3,2), C(k-3,3)…………C(k-3,k-3) 0 (n-1)^(k-3) = (n)^(k-3) 5 …………………… * 0 6 …………………… 0 7 …………………… 0 8 C(3,0), C(3,1), C(3,2), C(3,3) 0 (n-1)^(3) (n)^(3) 9 C(2,0), C(2,1), C(2,2) 0 (n-1)^(2) (n)^(2) 10 C(1,0), C(1,1) 0 (n-1)^(1) (n)^(1) 11 C(k,0), C(k,1), C(k,2), C(k,3)………… …… C(k,k) 1 s(n-1) s[n]
还有一点这道题有一个奇怪的mod数2^32对于这个膜数我们采用unsigned int自然溢出就好了,如果直接mod就会超时,这一点在以后遇到这个mod数的时候需要注意。
代码:
1 //Author: xiaowuga 2 #include<bits/c++.h> 3 #define maxx INT_MAX 4 #define minn INT_MIN 5 #define inf 0x3f3f3f3f 6 7 using namespace std; 8 typedef unsigned int ll; 9 long long n,size; 10 struct Matrix{ 11 ll mat[55][55]; 12 void clear(){ 13 memset(mat,0,sizeof(mat)); 14 } 15 Matrix operator * (const Matrix & m) const{ 16 Matrix tmp; 17 int i ,j,k; 18 tmp.clear(); 19 for( i=0;i<=size+1;i++) 20 for( k=0;k<=size+1;k++){ 21 if(mat[i][k]==0) continue; 22 for( j=0;j<=size+1;j++){ 23 tmp.mat[i][j]+=mat[i][k]*m.mat[k][j]; 24 //tmp.mat[i][j]%=MOD; 25 } 26 } 27 return tmp; 28 } 29 }; 30 Matrix POW(Matrix m,long long k){ 31 Matrix ans; 32 memset(ans.mat,0,sizeof(ans.mat)); 33 for(int i=0;i<=size+1;i++) ans.mat[i][i]=1; 34 while(k){ 35 if(k&1) ans=ans*m; 36 k=k>>1; 37 m=m*m; 38 } 39 return ans; 40 } 41 int main() { 42 ll tranangle[55][55]={0}; 43 tranangle[0][0]=1; 44 for(int i=1;i<55;i++){ 45 tranangle[i][0]=1; 46 for(int j=1;j<=i;j++) 47 tranangle[i][j]=tranangle[i-1][j]+tranangle[i-1][j-1]; 48 } 49 int T; 50 scanf("%d",&T); 51 for(int Case=1;Case<=T;Case++){ 52 scanf("%lld%lld",&n,&size); 53 Matrix m; 54 memset(m.mat,0,sizeof(m.mat)); 55 for(int i=0;i<=size;i++){ 56 for(int j=0;j<=size;j++) 57 m.mat[i][j]=tranangle[i][j]; 58 } 59 for(int i=0;i<=size;i++) 60 m.mat[size+1][i]=tranangle[size][i]; 61 m.mat[size+1][size+1]=1; 62 Matrix ans=POW(m,n-1); 63 ll sum=0; 64 for(int i=0;i<=size+1;i++){ 65 sum+=ans.mat[size+1][i]; 66 } 67 printf("Case %d: %lld ",Case,sum); 68 } 69 return 0; 70 }