• Gym101635C Macarons


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

    题目大意:

      给出一个 (N imes M) 的网格图,请你用 (1 imes 1) 和 (1 imes 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
    ",ans.mat[0][0]);
    85     return 0;
    86 }
    “这些年我一直提醒自己一件事情,千万不要自己感动自己。大部分人看似的努力,不过是愚蠢导致的。什么熬夜看书到天亮,连续几天只睡几小时,多久没放假了,如果这些东西也值得夸耀,那么富士康流水线上任何一个人都比你努力多了。人难免天生有自怜的情绪,唯有时刻保持清醒,才能看清真正的价值在哪里。”
  • 相关阅读:
    Springboot之配置定时任务
    Java之随机生成各种类型的数据举例
    docker安装postgresql 12.4
    Java随机生成字符串举例
    Java生成UUID
    Shell case 多选择语句用法举例
    Elasticsearch学习之集群高级网络设置
    交叉熵损失函数
    将博客搬至CSDN
    SonarQube服务搭建
  • 原文地址:https://www.cnblogs.com/Blogggggg/p/8711887.html
Copyright © 2020-2023  润新知