zoukankan      html  css  js  c++  java
  • hihocoder #1162 矩阵加速dp

    #1162 : 骨牌覆盖问题·三

    时间限制:10000ms
    单点时限:1000ms
    内存限制:256MB

    描述

    前两周里,我们讲解了2xN,3xN骨牌覆盖的问题,并且引入了两种不同的递推方法。
    这一次我们再加强一次题目,对于给定的K和N,我们需要去求KxN棋盘的覆盖方案数。

    提示:KxN骨牌覆盖

    输入

    第1行:2个整数N。表示棋盘宽度为k,长度为N。2≤K≤7,1≤N≤100,000,000

    输出

    第1行:1个整数,表示覆盖方案数 MOD 12357

    样例输入
    2 62247088
    样例输出
    1399
    #include<iostream>
    #include<cstdio>
    #include<cstring>
    using namespace std;
    const int MOD=12357;
    int m,n;
    struct Lu { int mx[140][140]; }L1,L2;
    void dfs(int now,int next,int col)
    {
        if(col==m){
            L1.mx[now][next]=1;//表示now状态能够转移到next状态
            return;
        }
        dfs((now<<1)+1,next<<1,col+1);//不放
        dfs(now<<1,(next<<1)+1,col+1);//竖放
        if(col+2<=m) dfs((now<<2)+3,(next<<2)+3,col+2);//横放
    }
    Lu multi(Lu a,Lu b)
    {
        Lu c;
        for(int i=0;i<(1<<m);i++){
            for(int j=0;j<(1<<m);j++){
                c.mx[i][j]=0;
                for(int k=0;k<(1<<m);k++)
                    c.mx[i][j]=(c.mx[i][j]+a.mx[i][k]*b.mx[k][j])%MOD;
            }
        }
        return c;
    }
    int solve(int x)
    {
        memcpy(L2.mx,L1.mx,sizeof(L1.mx));
        while(x){
            if(x&1) L1=multi(L1,L2);
            L2=multi(L2,L2);
            x>>=1;
        }
        return L1.mx[(1<<m)-1][(1<<m)-1];//最后放满,转移到末状态
    }
    int main()
    {
        while(scanf("%d%d",&m,&n)==2){
            memset(L1.mx,0,sizeof(L1.mx));
            dfs(0,0,0);
            int ans=solve(n-1);
            printf("%d
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    动态类(类工厂)总结
    m3u8字段意义解析
    libevent+bufferevent总结
    g++编译总结
    ffplay 参数说明分享
    PHP——最新号码归属地数据库
    PHP——汉字完美转为ASCII码
    PHP——json_encode转码保留中文
    workerman——报错
    PHP——封装Curl请求方法支持POST | DELETE | GET | PUT 等
  • 原文地址:https://www.cnblogs.com/--ZHIYUAN/p/7738859.html
Copyright © 2011-2022 走看看