某考试 T1 line
状压dp+矩阵转移,据说正解是dfs出的合法状态,,但难道不是三个for就行了吗2333
#include<iostream> #include<cmath> #include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #define ll long long const int ha=1000000007; using namespace std; int C[12][12],n,P,Q,cnt; struct node{ int a[3],full; }zt[233]; inline int add(int x,int y){ x+=y; return x>=ha?x-ha:x; } struct matrix{ int a[199][199]; inline void clear(){ memset(a,0,sizeof(a)); } matrix operator *(const matrix &u)const{ matrix r; r.clear(); for(int k=1;k<=cnt;k++) for(int i=1;i<=cnt;i++) for(int j=1;j<=cnt;j++) r.a[i][j]=add(r.a[i][j],a[i][k]*(ll)u.a[k][j]%ha); return r; } }base,ANS; inline void init(){ C[0][0]=1; for(int i=1;i<=8;i++){ C[i][0]=1; for(int j=1;j<=i;j++) C[i][j]=add(C[i-1][j-1],C[i-1][j]); } } inline void can(int i,int j){ node x=zt[i],y=zt[j]; if(y.a[1]<=x.a[0]&&y.a[2]<=x.a[1]&&x.full+(y.a[1]+y.a[2]==n?1:0)==y.full){ base.a[i][j]=C[x.a[0]][y.a[1]]*(ll)C[x.a[1]][y.a[2]]%ha; } } inline void build(){ for(int i=n;i>=0;i--) for(int j=(P==2?0:n-i);j>=0;j--) for(int l=0;l<=Q;l++) zt[++cnt]=(node){i,n-i-j,j,l}; base.clear(); for(int i=1;i<=cnt;i++) for(int j=1;j<=cnt;j++) can(i,j); } inline void solve(ll y){ ANS.clear(); for(int i=1;i<=cnt;i++) ANS.a[i][i]=1; int ans=0; for(;y;y>>=1,base=base*base) if(y&1) ANS=ANS*base; /* for(int i=1;i<=cnt;i++){ for(int j=1;j<=cnt;j++) printf("%d ",ANS.a[i][j]); puts(""); } */ for(int i=1;i<=cnt;i++) ans=add(ans,ANS.a[1][i]); printf("%d\n",ans); } int main(){ // freopen("line.in","r",stdin); // freopen("line.out","w",stdout); init(); ll m; scanf("%d%lld%d%d",&n,&m,&P,&Q); if(P==1){ puts("1"); return 0; } build(); solve(m); return 0; }
我爱学习,学习使我快乐