骨牌覆盖问题总结!hihoCoder/ NYOJ-1273宣传墙1151

 本想着做一下第九届河南省省赛题,结果被这个类似骨牌覆盖的题卡住了,队友然我去hihoCoder上老老实实把骨牌覆盖一、二、三做完,这题就没什么问题了。虽然很不情愿,但还是去见识了一下。

 骨牌覆盖问题主要解决用1*2的骨牌来覆盖K*N的棋盘,求有多少种覆盖方法。k一般在7以内。比如hihocoder #1143用1*2的骨牌覆盖2*N的棋盘,很明显是个斐波那契数列。hihocider#1151问题上升到用1*2的骨牌覆盖3*N的棋盘。再上升到#1162的k*N的棋盘。

                                                                    

                                                                           #1143 : 骨牌覆盖问题·一

 我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘。对于这个棋盘,一共有多少种不同的覆盖方法呢?
    由于本题N很大,所以利用矩阵快速幂来优化。
   以上便是一个裸的矩阵快速幂求斐波那契第N项了。可参考:矩阵快速幂


  

                                                                 #1151 : 骨牌覆盖问题·二

    对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?很显然N为奇数是不可能的。

     提示:3xN骨牌覆盖

                                                                 #1162 : 骨牌覆盖问题·三

   对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数。棋盘宽度为k,长度为N。2≤K≤7,1≤N≤100,000,000

    有了上面的基础,如何来解决第九届河南省省赛的那道类似骨牌覆盖问题呢。

   基于数据较小,队友是强行dp过去的,但对于我这种dp弱渣还是老老实实用矩阵快速幂来的更快些。

  

宣传墙

时间限制: 1000 ms  |  内存限制: 65535 KB
难度: 4

  一条4*N道路被分为左右两个矩形,然后用1*2的骨牌去覆盖,求各有多少种方法。很明显左边矩形是4*(M-1),右边矩形是4*(N-M-K+1)。其实根据骨牌覆盖三我们很容易得到k为4的系数矩阵。只需在上面的代码将k改为4即可。

struct martix
{
    ll  a[150][150];
};
int k,n,m,kk;
martix mul(martix A,martix B)
{
    martix res;
    memset(res.a,0,sizeof(res.a));
    for(int i=0; i<16; i++)
        for(int j=0; j<16; j++)
            for(int k=0; k<16; k++)
            res.a[i][j]=(res.a[i][j]+A.a[i][k]*B.a[k][j])%MOD;
    return res;
}
martix fast(martix tmp,int num)
{
    martix res;
    memset(res.a,0,sizeof(res.a));
    for(int i=0; i<16; i++) res.a[i][i]=1;
    while(num)
    {
        if(num&1) res=mul(res,tmp);
        tmp=mul(tmp,tmp);
        num>>=1;
    }
    return res;
}
void dfs(int x,int y,int num,martix &res,martix &ans)
{
    if(num==k)
    {
        res.a[y][x]=1;
        ans.a[y][x]=1;
        return ;
    }
    dfs(x<<1,(y<<1)+1,num+1,res,ans);//加减比左移优先级高
    dfs((x<<1)+1,y<<1,num+1,res,ans);
    if(num+2<=k) dfs((x<<2)+3,(y<<2)+3,num+2,res,ans);
}
void solve()
{
    k=4;
    martix res,ans;
    memset(res.a,0,sizeof(res.a));
    memset(ans.a,0,sizeof(ans.a));
    dfs(0,0,0,res,ans);
    res=fast(res,m-1);
    int ans1=res.a[15][15];
    ans=fast(ans,n-m-kk+1);
    int ans2=ans.a[15][15];
    printf("%d %d\n",ans1,ans2);
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {scanf("%d%d%d",&n,&m,&kk);
        solve();
    }
    return 0;
}

本想着和队友探讨一下如果单位矩阵不是1*2的,而是2*3或者其它的怎么做,然而队友推翻了我这种想法,也许出题人不会这样出题。有兴趣可以一(不)起(惜)探(赐)讨(教)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值