hdu 4602 Partition

// 列出了 n=5 时 5,4,3,2,1 出现的次数为 1 2 5 12 28
f[n+1]=3*f[n]-f[n-1]-f[n-2]-..f[1]
f[n]=3*f[n-1]-f[n-2]-..f[1]
==> f[n+1]=4*f[n]-4*f[n-1]
矩阵快速运算就可以得出答案了
// 开始提交时老错 结果是被 k>n 这种数据给坑了、、郁闷

#include <iostream> #include <algorithm> #include <queue> #include <math.h> #include <stdio.h> #include <string.h> using namespace std; void deal(__int64 a[2][2],__int64 n,int m){ __int64 b[2][2],c[2][2]; int i,j; for(i=0;i<2;i++) for(j=0;j<2;j++) b[i][j]=a[i][j]; a[0][0]=1;a[0][1]=0; a[1][0]=0;a[1][1]=1; __int64 t=1; for(;t<=n;t=t<<1){ if(t&n){ c[0][0]=((b[0][0]*a[0][0])%m+(b[0][1]*a[1][0])%m)%m; c[0][1]=((b[0][0]*a[0][1])%m+(b[0][1]*a[1][1])%m)%m; c[1][0]=((b[1][0]*a[0][0])%m+(b[1][1]*a[1][0])%m)%m; c[1][1]=((b[1][0]*a[0][1])%m+(b[1][1]*a[1][1])%m)%m; for(i=0;i<2;i++) for(j=0;j<2;j++) a[i][j]=c[i][j]; } c[0][0]=((b[0][0]*b[0][0])%m+(b[0][1]*b[1][0])%m)%m; c[0][1]=((b[0][0]*b[0][1])%m+(b[0][1]*b[1][1])%m)%m; c[1][0]=((b[1][0]*b[0][0])%m+(b[1][1]*b[1][0])%m)%m; c[1][1]=((b[1][0]*b[0][1])%m+(b[1][1]*b[1][1])%m)%m; for(i=0;i<2;i++) for(j=0;j<2;j++) b[i][j]=c[i][j]; } } int main() { int n,k; int num; int MOD=1000000007; __int64 ar[2][2]; int T; scanf("%d",&T); while(T--){ scanf("%d %d",&n,&k); if(k>n) {printf("0 ");continue;} ar[0][0]=4; ar[0][1]=-4; ar[1][0]=1; ar[1][1]=0; num=n-k+1; if(num==1){printf("1 ");continue;} if(num==2){printf("2 ");continue;} if(num==3){printf("5 ");continue;} deal(ar,num-3,MOD); int ans=0; ans=((ar[0][0]*5+ar[0][1]*2)%MOD+MOD)%MOD; printf("%d ",ans); } return 0; }
原文地址:https://www.cnblogs.com/372465774y/p/3209315.html