题意:给你n和k,要你求出(1K + 2K + 3K + ... + NK) % 232
这道题暴露了我好多问题,好像本来就有很多问题!
首先对数字不敏感,这个数字可以通过开unsigned int让它自然溢出。所以不用模运算,用模运算反而会超时。
然后就是公式的设置,这个不用多说,设f(n)=(1^k+...+n^k),自然就可以得到f(n)=f(n-1)+n^k,然后就是做这类题目的常见套路,不是从f(n)想递推公式,而是通过f(n+1),为什么这样,原因是这样式子会整齐一点,好看一点!
然后程序一定要该写的地方数值一定要写对,一定要写对!
接下来是代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ll; 4 ll C[60][60]; 5 int t; 6 long long n,k1,mod=1; 7 ll lc[60][60],ans[60][2]; 8 9 10 void init(){ 11 memset(lc,0,sizeof(lc)); 12 memset(ans,0,sizeof(ans)); 13 for(int i=1;i<=k1+2;i++) ans[i][1]=1; 14 for(int i=1;i<=k1+2;i++){ 15 if(i==1){ 16 lc[1][1]=1; 17 for(int j=2;j<=k1+2;j++) lc[1][j]=C[k1][j-2]; 18 }else{ 19 for(int j=i;j<=k1+2;j++) lc[i][j]=C[k1-i+2][j-i]; 20 } 21 } 22 } 23 24 void C_(){ 25 C[0][0]=1; 26 for(int i=1;i<=55;i++){ 27 C[i][0]=C[i][i]=1; 28 for(int j=1;j<i;j++){ 29 C[i][j]=(C[i-1][j-1]+C[i-1][j]); 30 } 31 } 32 } 33 34 void mul(){ 35 ll temp[60][2]; 36 memset(temp,0,sizeof(temp)); 37 for(int i=1;i<=k1+2;i++){ 38 for(int j=1;j<=1;j++){ 39 for(int k=1;k<=k1+2;k++){ 40 temp[i][j]=(temp[i][j]+lc[i][k]*ans[k][j]); 41 } 42 } 43 } 44 for(int i=1;i<=k1+2;i++) ans[i][1]=temp[i][1]; 45 } 46 47 void add(){ 48 ll temp[60][60]; 49 memset(temp,0,sizeof(temp)); 50 for(int i=1;i<=k1+2;i++){ 51 for(int j=1;j<=k1+2;j++){ 52 for(int k=1;k<=k1+2;k++){ 53 temp[i][j]=(temp[i][j]+lc[i][k]*lc[k][j]); 54 } 55 } 56 } 57 for(int i=1;i<=k1+2;i++) 58 for(int j=1;j<=k1+2;j++) 59 lc[i][j]=temp[i][j]; 60 } 61 62 void fast_pow(long long m){//这些参数的传递一定要非常非常小心 63 while(m){ 64 if(m%2==1) mul(); 65 add(); 66 m/=2; 67 } 68 cout<<ans[1][1]<<endl; 69 } 70 71 int main(){ 72 C_(); 73 cin>>t; 74 for(int i=1;i<=32;i++) mod*=2; 75 for(int kase=1;kase<=t;kase++){ 76 cin>>n>>k1; 77 if(n==1){ 78 cout<<"Case "<<kase<<": 1"<<endl; 79 continue; 80 } 81 if(k1==0){ 82 cout<<"Case "<<kase<<": "<<n%mod<<endl; 83 continue; 84 } 85 init(); 86 cout<<"Case "<<kase<<": "; 87 fast_pow(n-1); 88 } 89 return 0; 90 }