题目1 : 骨牌覆盖问题·一 (线性递推+矩阵快速幂)

题目来源

hiho一下 第四十一周

正在进行: 2天05小时28分钟25秒

首页

题目列表

我的提交

排名

讨论

报名人数:1264

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

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

骨牌,一种古老的玩具。今天我们要研究的是骨牌的覆盖问题:

我们有一个2xN的长条形棋盘,然后用1x2的骨牌去覆盖整个棋盘。对于这个棋盘,一共有多少种不同的覆盖方法呢?

举个例子,对于长度为1到3的棋盘,我们有下面几种覆盖方式:

提示:骨牌覆盖

提示:如何快速计算结果

输入

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

输出

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

样例输入

62247088

样例输出

17748018

入门的模板

#include<cstdio>
#include<algorithm>
#include<cmath>
#include<bits/stdc++.h>
using namespace std;
template<class T>inline T read(T&x)
{
    char c;
    while((c=getchar())<=32)if(c==EOF)return 0;
    bool ok=false;
    if(c=='-')ok=true,c=getchar();
    for(x=0; c>32; c=getchar())
        x=x*10+c-'0';
    if(ok)x=-x;
    return 1;
}
template<class T> inline T read_(T&x,T&y)
{
    return read(x)&&read(y);
}
template<class T> inline T read__(T&x,T&y,T&z)
{
    return read(x)&&read(y)&&read(z);
}
template<class T> inline void write(T x)
{
    if(x<0)putchar('-'),x=-x;
    if(x<10)putchar(x+'0');
    else write(x/10),putchar(x%10+'0');
}
template<class T>inline void writeln(T x)
{
    write(x);
    putchar('\n');
}
//-------ZCC IO template------
const int maxn=1000001;
const double inf=999999999;
#define lson (rt<<1),L,M
#define rson (rt<<1|1),M+1,R
#define M ((L+R)>>1)
#define For(i,t,n) for(int i=(t);i<(n);i++)
typedef long long  LL;
typedef double DB;
typedef pair<int,int> P;
#define bug printf("---\n");
#define mod  1000000007

typedef struct Matrix
{
    LL m[3][3];
}mat;

mat mul(mat a,mat b)
{
    mat c;
    memset(c.m,0,sizeof(c.m));
    for(int i=0;i<1;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
                c.m[i][j]+=((a.m[i][k]*b.m[k][j])%mod+mod)%mod;
    return c;
}

mat mu(mat a,mat b)
{
    mat c;
    memset(c.m,0,sizeof(c.m));
    for(int i=0;i<2;i++)
        for(int j=0;j<2;j++)
            for(int k=0;k<2;k++)
                c.m[i][j]+=((a.m[i][k]*b.m[k][j])%mod+mod)%mod;
    return c;
}
mat matpow(mat a,int n)
{
    mat rec;
    memset(rec.m,0,sizeof(rec.m));
    rec.m[0][0]=rec.m[1][1]=rec.m[2][2]=1;
    while(n)
    {
        if(n&1)
            rec=mu(rec,a);
        a=mu(a,a);
        n>>=1;
    }
    return rec;
}

int main()
{
    //#ifndef ONLINE_JUDGE
    //freopen("in.txt","r",stdin);
    //freopen("zccccc.txt","w",stdout);
    //#endif // ONLINE_JUDGE
    int n,m,i,j,t,k;

    while(read(n))
    {
        mat a,b;
        a.m[0][0]=0;
        a.m[0][1]=1;
        b.m[0][0]=0;
        b.m[0][1]=b.m[1][0]=b.m[1][1]=1;
        //mat c=mul(a,b);
        //printf("%d %d \n%d %d\n",c.m[0][0],c.m[0][1],c.m[1][0],c.m[1][1]);
        writeln(mul(a,matpow(b,n-1)).m[0][1]%mod);
    }
    return 0;
}
时间: 2024-10-05 07:18:54

题目1 : 骨牌覆盖问题·一 (线性递推+矩阵快速幂)的相关文章

HDU 5950 Recursive sequence 【递推+矩阵快速幂】 (2016ACM/ICPC亚洲区沈阳站)

Recursive sequence Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 249    Accepted Submission(s): 140 Problem Description Farmer John likes to play mathematics games with his N cows. Recently, t

2014 BNU 邀请赛E题(递推+矩阵快速幂)

Elegant String 题意:给定一个字符串,由0-k数字组成,要求该串中,子串不包含0-k全排列的方案数 思路:dp[i][j]表示放到i个数字,后面有j个不相同,然后想递推式,大概就是对应每种情况k分别能由那几种状态转移过来,在纸上画画就能构造出矩阵了,由于n很大,所以用快速幂解决 代码: #include <stdio.h> #include <string.h> const long long MOD = 20140518; int t; long long n; i

hdu 2604 递推 矩阵快速幂

HDU 2604 Queuing (递推+矩阵快速幂) 这位作者讲的不错,可以看看他的 #include <cstdio> #include <iostream> #include <algorithm> #include <cmath> #include <cstring> using namespace std; const int N = 5; int msize, Mod; struct Mat { int mat[N][N]; }; M

HDU 2604 Queuing (递推+矩阵快速幂)

[题目链接]:click here~~ [题目大意]: n个人排队,f表示女,m表示男,包含子串'fmf'和'fff'的序列为O队列,否则为E队列,有多少个序列为E队列. [思路]: 用f(n)表示n个人满足条件的结果,那么如果最后一个人是m的话,那么前n-1个满足条件即可,就是f(n-1): 如果最后一个是f那么这个还无法推出结果,那么往前再考虑一位:那么后三位可能是:mmf, fmf, mff, fff,其中fff和fmf不满足题意所以我们不考虑,但是如果是 mmf的话那么前n-3可以找满足

HDU2604-Queuing(递推+矩阵快速幂)

题目链接 题意:男为f,女为m,求在长度为L的队列中不存在fmf,fff这样子序列的序列的个数. 思路:又是递推题,假设长度为L的队列中存在的序列个数为f(L),那么考虑最后一个放的字母,假设最后一个放m,那么前L-1个可以随意排列,即个数为f(L - 1):如果最后一个放f,那么考虑后两个字母,可能出现的情况为ff,mf,这样比较难判断是否符合题目要求的,所以我们考虑后三个字母,可能出现的情况就为fff,mff,fmf,mmf,显而易见mff,mmf符合题意.当后三个为mmf时,前L-3个可以

HDU 2842 (递推+矩阵快速幂)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2842 题目大意:棒子上套环.第i个环能拿下的条件是:第i-1个环在棒子上,前i-2个环不在棒子上.每个环可以取下或放上,cost=1.求最小cost.MOD 200907. 解题思路: 递推公式 题目意思非常无聊,感觉是YY的. 设$dp[i]$为取第i个环时的总cost. $dp[1]=1$,$dp[2]=2$,前两个环取下是没有条件要求的. 从i=3开始,由于条件对最后的环限制最大,所以从最后一

2017中国大学生程序设计竞赛 - 女生专场 Happy Necklace(递推+矩阵快速幂)

Happy Necklace Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 1146    Accepted Submission(s): 491 Problem Description Little Q wants to buy a necklace for his girlfriend. Necklaces are single

Recursive sequence HDU - 5950 (递推 矩阵快速幂优化)

题目链接 F[1] = a, F[2] = b, F[i] = 2 * F[i-2] + F[i-1] + i ^ 4, (i >= 3) 现在要求F[N] 类似于斐波那契数列的递推式子吧, 但是N最大能到int的最大值, 直接循环推解不了 所以就得用矩阵快速幂咯 现在就看转移矩阵长什么样了 Mi表示要求的矩阵 转移矩阵用A表示 A * Mi = Mi+1 矩阵Mi里面至少得有 F[i-1] F[i-2] i ^ 4 Mi+1就相应的有 F[i] F[i-1] (i+1)^4 (i+1)^4 =

POJ3420 递推+矩阵快速幂

POJ3420 很有趣的覆盖问题 递归推导如下: f[n] = f[n-1] + 4*f[n-2] + 2 * [ f[n-3] + f[n-5] + f[n-7] +.... ] + 3 *  [ f[n-4] + f[n-6] + f[n-8] +.... ] ; (1) f[n - 2] = f[n-3] + 4*f[n-4] + 2 * [ f[n-5] + f[n-7] + f[n-9] +.... ] + 3 *  [ f[n-6] + f[n-8] + f[n-10] +....