• 斐波那契数列 改1 3*N 骨牌覆盖 改1 hiho一下 第四十二周 递归不行 矩阵加速


    题目1 : 骨牌覆盖问题·二

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

    描述

    上一周我们研究了2xN的骨牌问题,这一周我们不妨加大一下难度,研究一下3xN的骨牌问题?
    所以我们的题目是:对于3xN的棋盘,使用1x2的骨牌去覆盖一共有多少种不同的覆盖方法呢?
    首先我们可以肯定,奇数长度一定是没有办法覆盖的;对于偶数长度,比如2,4,我们有下面几种覆盖方式:

    提示:3xN骨牌覆盖

    输入

    第1行:1个整数N。表示棋盘长度。1≤N≤100,000,000

    输出

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

    样例输入
    62247088
    样例输出
    4037



    #include <iostream>
    #include <vector>
    using namespace std;
    #define modnum 12357
    typedef vector<long long> matrow;
    typedef vector<matrow> mat;
    mat build(long long x,long long y,long long a[])
    {
        mat ans;
        for(long long i=0;i<x;i++)
        {
            ans.push_back(matrow());
            for(long long j=0;j<y;j++)
            {
                ans[i].push_back(a[i*y+j]);
            }
        }
        return ans;
    }
    mat multi(const mat mat1,const mat mat2)
    {
        long long temp=0;
        long long rownum=mat1.size();
        long long colnum=mat2[0].size();
        long long nummul=mat1[0].size();
        mat ans;
        for(long long i=0;i<rownum;i++)
        {
            ans.push_back(matrow());
            for(long long j=0;j<colnum;j++)
            {
                temp=0;
                for(long long t=0;t<nummul;t++)
                    temp+=mat1[i][t]*mat2[t][j];
                ans[i].push_back(temp%modnum);
            }
        }
        return ans;
    }
    
    int main()
    {
        long long N;
        long long a[]={3,1,2,1};
        long long b[]={3,2};
        cin>>N;
    	if(N%2==1){ cout<<0<<endl; return 0; }
        mat ans=build(2,1,b);
        mat temp=build(2,2,a);
        long long n=N/2-1;
        if(n==0)cout<<3<<endl;
        if(n==1)cout<<11<<endl;
        if(n!=1&&n!=0)
        {
    		while(n)
    		{
    			if(n&1==1)
    				ans=multi(temp,ans);
    			temp=multi(temp,temp);
    			n=n>>1;
    		}
    	}
    	cout<<ans[0][0]<<endl;
        return 0;
    }
    

      

    这一期的问题和上一期的一样,也是使用矩阵乘法加速,

    用Xn表示N的排列总数

    用Tn表示N的特殊排列总数(特殊排列:最后一列有竖直骨牌如:n=2时 第二第三个骨牌。 n=4时2 4 6 7 8 10 11)

    N+2的排列总数 = “N的排列总数 拼接上n=2时的排列” + “N的特殊排列  拼接上n=2时第一个骨牌  并进行微调”

    ( “N的特殊排列  接上n=2时第一个骨牌  并进行微调” 参见n=4时 4和8 ,通过n=4时 9和5调整获得 )

    Xn+2=Xn*3+Tn

    N+2的特殊排列=“N的排列总数,拼接上n=2时 2 3 骨牌”+ “N的特殊排列 ,拼接上n=2时第一个骨牌 并进行微调”

    Tn+2=Xn*2+Tn

    用矩阵表示:

    |Xn+2m|    =   |3   1|    ^m-1    |3|

    |Tn+2m|          |2   1|                 |2|

  • 相关阅读:
    雷观(四):手机不可能取代电脑
    小雷FansUnion:我有了第一个付费客户(第一个徒弟)
    小雷FansUnion:我有了第一个付费客户(第一个徒弟)
    博客搬家算法伪码
    博客搬家算法伪码
    MySQL数据库定时自动备份脚本
    Java实现 LeetCode 386 字典序排数
    Java实现 LeetCode 386 字典序排数
    Java实现 LeetCode 386 字典序排数
    Java实现 LeetCode 385 迷你语法分析器
  • 原文地址:https://www.cnblogs.com/tjsudys/p/4438831.html
Copyright © 2020-2023  润新知