HDU - 6185 Covering(暴搜+递推+矩阵快速幂)

Covering

Bob‘s school has a big playground, boys and girls always play games here after school.

To protect boys and girls from getting hurt when playing happily on the playground, rich boy Bob decided to cover the playground using his carpets.

Meanwhile, Bob is a mean boy, so he acquired that his carpets can not overlap one cell twice or more.

He has infinite carpets with sizes of 1×21×2 and 2×12×1, and the size of the playground is 4×n4×n.

Can you tell Bob the total number of schemes where the carpets can cover the playground completely without overlapping?

InputThere are no more than 5000 test cases.

Each test case only contains one positive integer n in a line.

1≤n≤10181≤n≤1018 
OutputFor each test cases, output the answer mod 1000000007 in a line. 
Sample Input

1
2

Sample Output

1
5

题意:用1*2铺满4*n的地面。特别综合的一道题。求法是先用模拟暴搜找出初始几个n的情况,//1 5 11 36 95 281 781 2245 6336 18061

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MAX 1005
#define INF 0x3f3f3f3f
#define MOD 1000000007
using namespace std;
typedef long long ll;

int b[5][MAX];
int n;
ll ans;

void dfs(int s){
    int i,j;
    if(s==4*n){
        ans++;
        return;
    }
    for(i=1;i<=4;i++){
        for(j=1;j<=n;j++){
            if(b[i][j]==0){
                if(i+1<=4){
                    if(b[i+1][j]==0){
                        b[i][j]=1;
                        b[i+1][j]=1;
                        dfs(s+2);
                        b[i][j]=0;
                        b[i+1][j]=0;
                    }
                }
                if(j+1<=n){
                    if(b[i][j+1]==0){
                        b[i][j]=1;
                        b[i][j+1]=1;
                        dfs(s+2);
                        b[i][j]=0;
                        b[i][j+1]=0;
                    }
                }
                return;
            }
        }
    }
}
int main()
{
    int i;
    while(~scanf("%d",&n)){
        memset(b,0,sizeof(b));
        ans=0;
        dfs(0);
        printf("%lld\n",ans);
    }
    return 0;
}


然后再找规律,猜想存在递推关系,项数可以一点点加,当用五层循环寻找递推系数关系时发现,存在一种相同的系数情况。//1 5 1 -1 0

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#define MAX 1005
#define INF 0x3f3f3f3f
#define MOD 1000000007
using namespace std;
typedef long long ll;

int x[]={0,1,5,11,36,95,281,781,2245,6336,18061};

void find(int i){
    for(int a=-10;a<=10;a++){
        for(int b=-10;b<=10;b++){
            for(int c=-10;c<=10;c++){
                for(int d=-10;d<=10;d++){
                    for(int e=-10;e<=10;e++){
                        if(a*x[i-1]+b*x[i-2]+c*x[i-3]+d*x[i-4]+e==x[i]){
                            printf("%d:%d %d %d %d %d\n",i,a,b,c,d,e);
                        }
                    }
                }
            }
        }
    }
}
int main()
{
    int n,i;
    for(i=5;i<=10;i++){
        find(i);
    }
    return 0;
}


最后确定递推公式:f[i]=f[i-1]+5*f[i-2]+f[i-3]-f[i-4]+0。(注意:负数系数取余时要先加再余)然后套矩阵快速幂。

#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#define MAX 10
#define MOD 1000000007
using namespace std;
typedef long long ll;

struct mat{
    ll a[MAX][MAX];
};

mat operator *(mat x,mat y)    //重载乘运算
{
    mat ans;
    memset(ans.a,0,sizeof(ans.a));
    for(int i=1;i<=4;i++){
        for(int j=1;j<=4;j++){
            for(int k=1;k<=4;k++){
                ans.a[i][j]+=(x.a[i][k]*y.a[k][j]+MOD)%MOD;    //先加后余,避免负数取模异常
                ans.a[i][j]%=MOD;
            }
        }
    }
    return ans;
}
mat qMod(mat a,ll n)    //矩阵快速幂
{
    mat t;
    t.a[1][1]=1;t.a[1][2]=5;t.a[1][3]=1;t.a[1][4]=-1;
    t.a[2][1]=1;t.a[2][2]=0;t.a[2][3]=0;t.a[2][4]=0;
    t.a[3][1]=0;t.a[3][2]=1;t.a[3][3]=0;t.a[3][4]=0;
    t.a[4][1]=0;t.a[4][2]=0;t.a[4][3]=1;t.a[4][4]=0;    //单位矩阵
    while(n){
        if(n&1) a=t*a;    //顺序不可颠倒
        n>>=1;
        t=t*t;
    }
    return a;
}
int main()
{
    ll n;
    while(~scanf("%I64d",&n)){
        if(n==1) printf("1\n");
        else if(n==2) printf("5\n");
        else if(n==3) printf("11\n");
        else if(n==4) printf("36\n");
        else{
            mat a;
            memset(a.a,0,sizeof(a.a));
            a.a[1][1]=36;
            a.a[2][1]=11;
            a.a[3][1]=5;
            a.a[4][1]=1;   //初始矩阵
            a=qMod(a,n-4);
            printf("%I64d\n",a.a[1][1]);
        }
    }
    return 0;
}

原文地址:https://www.cnblogs.com/yzm10/p/9313916.html

时间: 2024-10-18 18:38:30

HDU - 6185 Covering(暴搜+递推+矩阵快速幂)的相关文章

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

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

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 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开始,由于条件对最后的环限制最大,所以从最后一

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可以找满足

HDU6185 Covering (递推+矩阵快速幂)

大致题意:让你用1*2规格的地毯去铺4*n规格的地面,告诉你n,问有多少种不同的方案使得地面恰好被铺满且地毯不重叠.答案对1000000007取模 递推得f(n)=f(n-1)+5*f(n-2)+f(n-3)-f(n-4),因为n很大,所以接下来用矩阵快速幂搞搞就可以了. #include <iostream> #include <cstring> #include <cstdio> using namespace std; long long n; long long

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 =

递推+矩阵快速幂 HDU 2065

1 #include <iostream> 2 #include <cstring> 3 #include <cstdio> 4 5 using namespace std; 6 7 //矩阵大小上限 8 const int SIZ=100; 9 int MOD=100; 10 11 //矩阵大小为n*m,初始化全部为0 12 struct mat 13 { 14 int n,m; 15 int ar[SIZ][SIZ]; 16 mat() 17 { 18 memset

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个可以