标签:
前两周里,我们讲解了2xN,3xN骨牌覆盖的问题,并且引入了两种不同的递推方法。
这一次我们再加强一次题目,对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数。
第1行:2个整数N。表示棋盘宽度为k,长度为N。2≤K≤7,1≤N≤100,000,000
第1行:1个整数,表示覆盖方案数 MOD 12357
2 62247088
1399
解题:dfs造转移方程+dp计数+快速幂优化dp
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const LL mod = 12357; 5 int n,m; 6 struct Matrix{ 7 int m[1<<7][1<<7]; 8 Matrix(){ 9 init(); 10 } 11 void init(){ 12 memset(m,0,sizeof m); 13 } 14 Matrix operator*(const Matrix &rhs){ 15 Matrix ret; 16 for(int k = 0; k < (1<<n); ++k) 17 for(int i = 0; i < (1<<n); ++i) 18 for(int j = 0; j < (1<<n); ++j) 19 ret.m[i][j] = (ret.m[i][j] + m[i][k]*rhs.m[k][j])%mod; 20 return ret; 21 } 22 void print(){ 23 for(int i = 0; i < 8; ++i){ 24 for(int j = 0; j < 8; ++j) 25 printf("%d ",m[i][j]); 26 cout<<endl; 27 } 28 } 29 }; 30 Matrix a,b; 31 void quickPow(LL index){ 32 while(index){ 33 if(index&1) a = a*b; 34 index >>= 1; 35 b = b*b; 36 } 37 } 38 bool tab[10][10]; 39 void dfs(int cur,int st){ 40 if(cur >= n){ 41 int ss = 0; 42 for(int i = n-1; i >= 0; --i){ 43 ss <<= 1; 44 ss |= tab[i][1]; 45 } 46 b.m[st][ss]++; 47 return; 48 } 49 if(!tab[cur][0]){ 50 if(!tab[cur][1]){ 51 tab[cur][0] = tab[cur][1] = true; 52 dfs(cur+1,st); 53 tab[cur][0] = tab[cur][1] = false; 54 } 55 if(cur + 1 < n){ 56 if(!tab[cur+1][0]){ 57 tab[cur+1][0] = tab[cur][0] = true; 58 dfs(cur+2,st); 59 tab[cur+1][0] = tab[cur][0] = false; 60 } 61 } 62 }else dfs(cur + 1,st); 63 } 64 void init(int st){ 65 memset(tab,false,sizeof tab); 66 for(int i = 0,xst = st; i < n; ++i,xst >>= 1) 67 tab[i][0] = xst&1; 68 dfs(0,st); 69 } 70 int main(){ 71 while(~scanf("%d%d",&n,&m)){ 72 b.init(); 73 a.init(); 74 for(int i = 0; i < (1<<n); ++i) init(i); 75 a.m[0][0] = 1; 76 quickPow(m); 77 printf("%d\n",a.m[0][0]); 78 } 79 return 0; 80 }
标签:
原文地址:http://www.cnblogs.com/crackpotisback/p/4862296.html