zoukankan      html  css  js  c++  java
  • hihoCoder #1162 : 骨牌覆盖问题·三 (矩阵快速幂,DP)

    题意:有一个k*n的棋盘,要求用1*2的骨牌来铺满,有多少种方案?(k<8,n<100000001)

    思路:

      由于k是比较小,但是又不那么小,可以专门构造这样的一个矩阵M,使得只要我们有一个初始矩阵R,求得ans矩阵,然后答案就在ans中了。ans=R*Mn

      M的大小应该是2k*2k,所以当k稍微大一些就不合适存储这个矩阵了,而且里面大部分都是0,很浪费。由于k<8,所以M的大小为128*128是可以接受的。复杂度是O(23*k*logn),大概是千万级别的。

     1 #include <bits/stdc++.h>
     2 #define pii pair<int,int>
     3 #define INF 0x3f3f3f3f
     4 #define LL long long
     5 using namespace std;
     6 const int N=21000;
     7 const int mod=12357;
     8 int k, n;
     9 int M[130][130], grid[130][130], tot[130][130], cur[130][130];
    10 
    11 void DFS(int x,int y,int col)   //构造矩阵M。
    12 {
    13     if(col==k)
    14     {
    15         M[y][x]=1;              //表示y可以转移到x
    16         return ;
    17     }
    18     DFS(x<<1, (y<<1)+1, col+1);                      //不放
    19     DFS((x<<1)+1, y<<1, col+1);                      //放竖
    20     if(col+2<=k)    DFS((x<<2)+3, (y<<2)+3, col+2);  //放横
    21 }
    22 
    23 void mul(int A[][130],int B[][130])
    24 {
    25     for(int i=0; i<(1<<k); i++)
    26     {
    27         for(int j=0; j<(1<<k); j++)
    28         {
    29             int tmp=0;
    30             for(int q=0; q<(1<<k); q++)
    31             {
    32                 tmp+=A[i][q]*B[q][j];
    33                 tmp%=mod;
    34             }
    35             grid[i][j]=tmp;
    36         }
    37     }
    38     memcpy(A, grid, sizeof(grid));
    39 }
    40 
    41 
    42 int cal(int t)  //注意t=n-1
    43 {
    44     memset(M, 0, sizeof(M));
    45     memset(tot, 0, sizeof(tot) );
    46     memset(cur, 0, sizeof(cur) );
    47     DFS( 0, 0, 0);   //求矩阵。
    48     memcpy(cur, M, sizeof(M));
    49     while(t)
    50     {
    51         if(t&1) mul(M, cur);    //该位为1
    52         mul(cur, cur);  //矩阵自乘
    53         t>>=1;
    54     }
    55     return M[(1<<k)-1][(1<<k)-1];   //矩阵很特殊,只需要这一项。
    56 }
    57 
    58 int main()
    59 {
    60     //freopen("input.txt", "r", stdin);
    61     while(~scanf("%d%d", &k, &n))    printf("%d
    ", cal(n-1));
    62     return 0;
    63 }
    AC代码
  • 相关阅读:
    DRF版本控制
    Django Rest Framework 视图和路由
    ModelSerializer
    linux下jdk安装与配置
    linux下各种安装包下载地址
    Creating mailbox file: 文件已存在
    vim常用设置
    zookeeper集群搭建与升级
    linux下shell 脚本 中windows换行符换成linux换行符
    spring注解
  • 原文地址:https://www.cnblogs.com/xcw0754/p/4780744.html
Copyright © 2011-2022 走看看