多米诺骨牌 优化版
算法:
在之前搜索出状态的基础上,再压缩一次状态。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
//by yefeng #include<iostream> using namespace std; typedef long long LL; const int mod = 9937; int mask,idx, n , m; struct Matrix{ int mat[257][257]; void zero() { memset(mat,0,sizeof(mat)); } void unit(){ memset(mat,0,sizeof(mat)); for(int i = 0; i <= mask; i++) mat[i][i] = 1; } }A,T; Matrix operator *(const Matrix &a,const Matrix &b){ Matrix tmp; tmp.zero(); for(int i = 0; i < idx; i++){ for(int k = 0; k < idx; k++){ if( a.mat[i][k] == 0 ) continue; for(int j = 0; j < idx; j++){ tmp.mat[i][j] += (a.mat[i][k]*b.mat[k][j])%mod; tmp.mat[i][j] %= mod; } } } return tmp; } Matrix operator ^(Matrix x,int k){ Matrix tmp; tmp.unit(); while(k){ if(k&1) tmp = tmp*x; x = x*x; k >>= 1; } return tmp; } int vis[300],id[300],v[300]; //检查横放状态 bool check(int x){ bool flag=true; for(int i = 0; i < m; i++){ if( !( x &(1<<i) ) ) continue; //如果第i位不为1,就continue if( (i == m-1) || !( x & (1<<(i+1)) ) ){ //判断第i + 1位是否为1. flag = false; break; } i++; } return flag; } void DFS(int x){ if(vis[x]) return; vis[x]=1; if( id[x] == -1 ) id[x] = idx++; int c = (~x) & mask; for(int i = 0; i <= mask; i++){ if( (i&c) == c && check( i&x ) ){ //i&c == c保证两层之间不能同时有0 if(id[i] == -1) id[i] = idx++; T.mat[ id[i] ][ id[x] ] += 1; if( !vis[i] ) DFS(i); } } } void init(){ T.zero(); idx = 0; memset(vis,0,sizeof(vis)); memset(id,0xff,sizeof(id)); memset(v,0,sizeof(v)); idx = 0; DFS(mask); for(int i = 0; i <= mask; i++){ if( ~id[i] && T.mat[id[i]][0] ) v[ id[i] ] = 1; } } void solve(int k){ A = T^(k-1); LL res = 0; for(int i = 0; i < idx; i++) res = ( res+ v[i]*A.mat[i][0] ) % mod; printf("%I64d\n", res); } int main(){ //freopen("F.in", "r", stdin ); //freopen("1.out", "w", stdout ); int a, b; while( ~scanf("%d%d",&a,&b)){ n = max(a,b), m = min(a,b); if( m == 1 ){ if(n&1) puts("0"); else puts("1"); continue; } mask = (1<<m)-1; init(); solve(n); } }
posted on 2012-08-18 16:38 more think, more gains 阅读(207) 评论(0) 编辑 收藏 举报