HDU 5434
其实是一道状态DP题。都是行与行之间的转移,可以知道,当某j列中有一个象,如果存在情况i-1行j-1列有象而i,j-1位置无象则不可放,或者i-1,j+1有而i,j+1无同样不可放。
使用快速状态转移
#include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <queue> #include <cmath> using namespace std; const int mod=1000000007; const int MAX=(1<<7); int TranMatrix[MAX][MAX]; int tmp[MAX][MAX]; /* int mul(int a,int b){ int res=0; while(b){ if(b&1) res=(res+a)%mod; a=(a+a)%mod; b>>=1; } return res; } */ int quick(int Status,int n){ int ans[MAX][MAX],for_save[MAX][MAX]; memset(ans,0,sizeof(ans)); for(int i=0;i<MAX;i++) ans[i][i]=1; while(n){ if(n&1){ for(int i=0;i<Status;i++){ for(int j=0;j<Status;j++){ for_save[i][j]=0; for(int k=0;k<Status;k++){ for_save[i][j]=(for_save[i][j]+1LL*ans[i][k]*tmp[k][j]%mod); if(for_save[i][j]>mod) for_save[i][j]-=mod; } } } for(int i=0;i<Status;i++){ for(int j=0;j<Status;j++) ans[i][j]=for_save[i][j]; } } n>>=1; for(int i=0;i<Status;i++){ for(int j=0;j<Status;j++){ for_save[i][j]=0; for(int k=0;k<Status;k++){ for_save[i][j]=(for_save[i][j]+1LL*tmp[i][k]*tmp[k][j]%mod); if(for_save[i][j]>mod) for_save[i][j]-=mod; } } } for(int i=0;i<Status;i++){ for(int j=0;j<Status;j++) tmp[i][j]=for_save[i][j]; } } int res=0; for(int i=0;i<Status;i++) res=(res+ans[0][i])%mod; return res; } int main(){ int n,m; int Status=(1<<7); for(int i=0;i<(Status);i++){ for(int j=0;j<Status;j++){ bool flag=true; for(int k=0;k<7;k++){ if((((1<<k)&j)==(1<<k))&&(((1<<k)&i)==0)){ if((((1<<(k+1))&j)==0)&&(((1<<(k+1))&i)>0)){ flag=false; break; } else if(k>0&&((1<<(k-1))&j)==0&&(((1<<(k-1))&i)>0)){ flag=false; break; } } } TranMatrix[i][j]=flag?1:0; } } while(scanf("%d%d",&n,&m)!=EOF){ //swap(n,m); Status=1<<m; for(int i=0;i<Status;i++){ for(int j=0;j<Status;j++) tmp[i][j]=TranMatrix[i][j]; } printf("%d\n",quick(Status,n)); } return 0; }
矩阵可过。