Gym101635C Macarons

题目链接:http://codeforces.com/gym/101635/attachments

题目大意:

  给出一个 \(N \times M\) 的网格图,请你用 \(1 \times 1\) 和 \(1 \times 2\) 两种纸片填满该图,问有几种方案。

知识点:  矩阵快速幂、DFS

解题思路:

  做这道题如果没有思路的话,建议先看看 \(Matrix67\) 的这篇文章。这道题就是其中的经典题目九的变形。

  由于列数很少,所以我们可以利用列与列之间的状态转移。

  设矩阵 \(Mat[state1][state2]\),其代表填满当前列(当前列的初始状态为\(state1\))并且使得下一列状态为 \(state2\) 的方案数(每一列的状态无非就是这一列哪些格子已经被填,哪些还没被填,我们可以用一个二进制数来表示状态)。

  如此一来,我们就可以先用 \(dfs\) 来求出从第一列的各种状态转移到第二列的各种状态的方案数,然后求出 \(Mat\) 的 \(M\) 次幂 \(ans\) ,答案即为 \(ans[0][0]\).

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const ll mod=1e9;
 5 struct Matrix {
 6     int mat[260][260];
 7 };
 8 Matrix Multiply(Matrix x, Matrix y, int n) {
 9     Matrix temp;
10     memset(temp.mat, 0, sizeof(temp.mat));
11     for (int i = 0; i < n; i++) {
12         for (int j = 0; j < n; j++) {
13             for (int k = 0; k < n; k++) {
14                 ll tmp=(ll)x.mat[i][k] * y.mat[k][j]%mod;
15                 temp.mat[i][j] = (int)(((ll)temp.mat[i][j]+tmp)%mod);
16             }
17         }
18     }
19     return temp;
20 }
21 Matrix Fast_Power(Matrix a, ll m, int n) {
22     Matrix res;
23     memset(res.mat, 0, sizeof(res.mat));
24     for (int i = 0; i < n; i++)    res.mat[i][i] = 1;
25     
26     while (m) {
27         if (m & 1)    res = Multiply(res, a, n);
28         m >>= 1;
29         a = Multiply(a, a, n);
30     }
31     return res;
32 }
33 
34 Matrix ans;
35 void dfs(int org,int now,int nex,int n){
36     int one[10],two[10];
37     memset(one,0,sizeof(one));
38     memset(two,0,sizeof(two));
39     int tnex=nex,tnow=now;
40     int ind=0;
41     while(now){
42         one[ind]=now%2;
43         now>>=1;
44         ind++;
45     }
46     bool flag=true;
47     for(int i=0;i<n;i++){
48         if(one[i]!=1){
49             flag=false;
50             break;
51         }
52     }
53 
54     if(flag){
55         ans.mat[org][tnex]++;
56         return;
57     }
58     ind=0;
59     while(nex){
60         two[ind]=nex%2;
61         nex>>=1;
62         ind++;
63     }
64 
65     for(int i=0;i<n;i++){
66         if(one[i]==0){
67             dfs(org,tnow+(1<<i),tnex,n);
68             dfs(org,tnow+(1<<i),tnex|(1<<i),n);
69             if(i+1<n&&one[i+1]==0){
70                 dfs(org,tnow+(1<<i)+(1<<(i+1)),tnex,n);
71             }//为了避免重复,我们不在下一列放置 2*1 的纸片
72             break;
73         }
74     }
75 }
76 int main(){
77   //  freopen("in.txt","r",stdin);
78     int N;
79     ll M;
80     scanf("%d%lld",&N,&M);
81     for(int i=0;i<(1<<N);i++)
82         dfs(i,i,0,N);
83     ans=Fast_Power(ans,M,(1<<N));
84     printf("%d\n",ans.mat[0][0]);
85     return 0;
86 }

 

posted @ 2018-04-03 23:41  Blogggggg  阅读(572)  评论(0编辑  收藏  举报