骨牌覆盖小结

题目链接

棋盘规模 2*n  (n很大)

直接找出递推公式用矩阵快速幂求解

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=2;
const LL mod=19999997;
LL b[N]= {1,1};        //此处初始化列向量
LL hh[N][N]={{1,1},
             {1,0}
};

struct Mat
{
    LL mat[N][N];
    LL* operator [](int x)    //注意这种写法
    {
        return mat[x];
    }
} A;
Mat Mut(Mat a,Mat b)
{
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    for(int i=0; i<N; i++)
        for(int k=0; k<N; k++)    if(a[i][k])
            for(int j=0; j<N; j++)
            {
                c[i][j]+=a[i][k]*b[k][j]%mod;
                c[i][j]=c[i][j]%mod;
            }
    return c;
}
Mat Qpow(Mat a,LL n)
{
    Mat c;
    for(int i=0; i<N; ++i)
        for(int j=0; j<N; ++j)
            c[i][j]=(i==j);
    for(; n; n>>=1)
    {
        if(n&1) c=Mut(c,a);
        a=Mut(a,a);
    }
    return c;
}
LL cal(Mat A,LL n,LL b[])
{
    Mat A_=Qpow(A,n-1);
    LL ret=A_[0][0]*b[0]+A_[0][1]*b[1];
    return (ret+mod)%mod;
}
void init_A()
{
    for(int i=0; i<N; i++)
        for(int j=0; j<N; j++)
            A[i][j]=hh[i][j];
}

int main()
{
    LL n,ans;
    init_A();
    while(cin>>n)
    {
        ans=cal(A,n,b);        //假定下标从第1项开始计数,求第n项
        cout<<ans<<endl;
    }
} 

Lv. 0

题目链接

棋盘规模 k*n  (k<=7,n很大)

利用dfs推出状态转移矩阵(矩阵规模 (2k))

有一点要注意的是,比如说求的是两列的递推矩阵,那么前一列如果对应位是0,那么递推时,要在该位置横放一个骨牌,使当前列该为1

然后用矩阵快速幂求解

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=128;
const LL mod=12357;

int n,k,M;

LL b[N];//= {0,0,0,0,0,0,0,1};        //此处初始化列向量 

struct Mat
{
    LL mat[N][N];
    LL* operator [](int x)    //注意这种写法
    {
        return mat[x];
    }
} A;
Mat Mut(Mat a,Mat b)
{
    Mat c;
    memset(c.mat,0,sizeof(c.mat));
    for(int i=0; i<M; i++)
        for(int k=0; k<M; k++)    if(a[i][k])
            for(int j=0; j<M; j++)
            {
                c[i][j]+=a[i][k]*b[k][j]%mod;
                c[i][j]=c[i][j]%mod;
            }
    return c;
}
Mat Qpow(Mat a,LL n)
{
    Mat c;
    for(int i=0; i<M; ++i)
        for(int j=0; j<M; ++j)
            c[i][j]=(i==j);
    for(; n; n>>=1)
    {
        if(n&1) c=Mut(c,a);
        a=Mut(a,a);
    }
    return c;
}
LL cal(Mat A,LL n,LL b[])
{
    Mat A_=Qpow(A,n);
    return A_[M-1][M-1];
}
void dfs(int pre,int nxt,int col,Mat& A)
{
    if(col==k)
    {
        A[pre][nxt]=1;
        return ;
    }
    dfs(pre<<1,nxt<<1|1,col+1,A);
    dfs(pre<<1|1,nxt<<1,col+1,A);
    if(col+2<=k)    dfs(pre<<2|3,nxt<<2|3,col+2,A);
}

int main()
{
    while(cin>>k>>n)
    {
        memset(b,0,sizeof(b));
        M=1<<k;
        b[M-1]=1;
        memset(A.mat,0,sizeof(A.mat));
        dfs(0,0,0,A);
        LL ans=cal(A,n,b);        //假定下标从第1项开始计数,求第n项
        cout<<ans<<endl;
    }
} 

Lv. 1

题目链接

棋盘规模 n*m  (n,m<=11)

这时矩阵乘法的复杂度就太大了,可以直接利用利用递推关系搞

//#include<bits/stdc++.h>
#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
using namespace std;
typedef long long LL;
const int N=2048;

int n,k,M;
int A[13][N];

void dfs(int pre,int nxt,int col,int r)
{
    if(col==k)
    {
        A[r][nxt]+=A[r-1][pre];
        return ;
    }
    dfs(pre<<1,nxt<<1|1,col+1,r);
    dfs(pre<<1|1,nxt<<1,col+1,r);
    if(col+2<=k)    dfs(pre<<2|3,nxt<<2|3,col+2,r);
}

int main()
{
    while(cin>>k>>n)
    {
//        cout<<k<<‘ ‘<<n<<endl;
        if(k==0&&n==0)
            break;
        if(k%2&&n%2)
        {
            puts("0");
            continue;
        }
        memset(A,0,sizeof(A));
        if(k>n) swap(k,n);
        M=1<<k;
        A[0][M-1]=1;
        for(int i=1;i<=n;i++)
            dfs(0,0,0,i);
        LL ans=A[n][M-1];
        cout<<ans<<endl;
    }
} 

Lv. 2

未解决

题目链接

棋盘规模 n*m  (n,m<=100)

唐老师博客

感觉这题应该不会考吧,出题人似乎是看过论文之后,强行按照论文出了个题

题目链接

棋盘规模 n*m  (n,m<=16)

稳定/免分割线多米诺骨牌的棋盘覆盖问题

要利用前面的Lv. 2的方法打表,然后用容斥原理解决,目前还不是很懂

时间: 2024-08-28 12:36:54

骨牌覆盖小结的相关文章

编程之美 --1 : 骨牌覆盖问题&#183;一

题目1 : 骨牌覆盖问题·一 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题:我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢?举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 提示:骨牌覆盖 提示:如何快速计算结果 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 1999

随便玩玩系列之一:SPOJ-RNG+51nod 算法马拉松17F+51nod 1034 骨牌覆盖v3

先说说前面的SPOJ-RNG吧,题意就是给n个数,x1,x2,...,xn 每次可以生成[-x1,x1]范围的浮点数,把n次这种操作生成的数之和加起来,为s,求s在[A,B]内的概率 连续形的概率,想象为一个n维长方体,有两个平面与这个几何图形相割,于是就变成了求面(体)积问题,一般要去重,n维区域系数:s^n/n!,至于区间问题,直接前缀之差搞定 然后就是悲催的算法马拉松17F题了...其实是道好题来的,只是出题人不知世界上还有这题,然后某大牛把思路理清后把答案直接搬了过来 经典的1*2骨牌覆

hihoCoder #1162 : 骨牌覆盖问题&#183;三

#1162 : 骨牌覆盖问题·三 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 前两周里,我们讲解了2xN,3xN骨牌覆盖的问题,并且引入了两种不同的递推方法.这一次我们再加强一次题目,对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数. 提示:KxN骨牌覆盖 输入 第1行:2个整数N.表示棋盘宽度为k,长度为N.2≤K≤7,1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 1235

[hihoCoder] 题目1 : 骨牌覆盖问题&#183;二

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 12

hihoCoder 骨牌覆盖问题&#183;一 hiho一下 第四十一周

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 骨牌,一种古老的玩具.今天我们要研究的是骨牌的覆盖问题:我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘.对于这个棋盘,一共有多少种不同的覆盖方法呢?举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式: 提示:骨牌覆盖 提示:如何快速计算结果 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 19999997 样例输入 62247

骨牌覆盖

P2070 - 骨牌覆盖 Description 有一个3*n的棋盘让你放入若干1*2的骨牌,要求将整棋盘恰好覆盖满.求方案数! Input 一个整数n. Output 方案数模12357的值. Sample Input 2 Sample Output 3 Hint 1<=n<=100000000 td p { margin-bottom: 0cm } pre.cjk { font-family: "Droid Sans Fallback", monospace } p {

hihoCode #1151 : 骨牌覆盖问题&#183;二

#1151 : 骨牌覆盖问题·二 Time Limit:10000ms Case Time Limit:1000ms Memory Limit:256MB 描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.

3xN骨牌覆盖——hihoCoder

3xN骨牌覆盖 在2xN的骨牌覆盖问题中,我们有递推式子 (0,1)xM^n=(f[n-1],f[n]). 我们考虑能否在3xN的情况下找到同样的式子. 但在实际的推导过程可以发现,对于3xN的覆盖,对应的f数值公式比2xN复杂太多.我们需要换个角度来思考推导公式. 在我们放置骨牌的过程中,一定是放好一行之后再放置下一行.根据摆放的方式,可能会产生很多种不同的形状,而这些形状之间是否具有某些递推关系呢? 如果他们存在一定的递推关系,则我们可以根据第i行的方案数来推导第i+1行的方案数.这样一行一

hiho42 : 骨牌覆盖问题&#183;二

描述 上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?首先我们可以肯定,奇数长度一定是没有办法覆盖的:对于偶数长度,比如2,4,我们有下面几种覆盖方式: 提示:3xN骨牌覆盖 输入 第1行:1个整数N.表示棋盘长度.1≤N≤100,000,000 输出 第1行:1个整数,表示覆盖方案数 MOD 12357 样例输入 62247088 样例输出 4037 提示:3xN骨牌