2020/5/10 模拟赛 Day6 T2 操场

戏子无情 提交于 2020-08-17 20:13:46

题面

Solution

先从n较小的情况枚举找规律

这是$n=1$时的情况,只有1种摆放方式;

 $$f_{1}=1$$

这是$n=2$时的摆放方式,共有5种摆放方式;

$$f_{2}=5$$

在考虑$n=3$时的摆放方式时,可以想到用$n=2$和$n=1$时的情况进行组合


所以这是就有$2\times 1\times 5$种方式(第一列使用$n=1$时情况,2、3列使用$n=2$时情况  以及  1、2列使用$n=2$时情况,3列使用$n=1$时情况)

第2行第1列的情况是重复的,因为$n=2$中的第一种情况其实就是$n=1$的情况的拼接,所以再使用这个情况进行组合就会出现重复,所以真正能用于组合的$n=2$的情况只有后4种。

但是仍然有情况遗漏:

这两种情况无论如何都不能分割成$n=1$和$n=2$情况的组合。

 $$f_{3}=f_{2}+4f_{1}+2f_{0}+3 \times 0$$

同样地,在$n=4$时也会发现有一些情况不能由之前的任意一种情况拼接而来

$$f_{4}=f_{3}+4f_{2}+2f_{1}+3f_{0}\left ( f_{0}=1 \right )$$

继续列举下去,会发现每一个$n\left ( n\geq 3 \right )$,当$n$为奇数,就会找到2种无法组合的情况,偶数时则会找到3种。

$$f_{n}=f_{n-1}+4f_{n-2}+2\left ( f_{n-3}+f_{n-5}+\cdots +f_{1}/f_{0} \right )+3\left ( f_{n-4}+f_{n-6}+\cdots +f_{0}/f_{1} \right )$$

$$f_{n}=f_{n-1}+4f_{n-2}+2\left ( f_{n-3}+f_{n-4}+\cdots +f_{1}/f_{0} \right )+ f_{n-4}+f_{n-6}+\cdots +f_{0}/f_{1} $$

$$f_{n-2}=f_{n-3}+4f_{n-4}+2\left ( f_{n-5}+f_{n-6}+\cdots +f_{1}/f_{0} \right )+ f_{n-6}+f_{n-8}+\cdots +f_{0}/f_{1} $$

两式相减得

$$f_{n}-f_{n-2}=f_{n-1}+4f_{n-2}+f_{n-3}-f_{n-4}$$

$$f_{n}=f_{n-1}+5f_{n-2}+f_{n-3}-f_{n-4}$$

使用矩阵快速幂求解

#include<iostream>
#include<cstring>
#include<cstdio>
using namespace std;
long long n;
const long long mod=1000000007;
struct Matrix
{
    long long a[10][10];
    Matrix()
    {
        memset(a,0,sizeof(a));
    }
}G,F;
inline long long read()
{
    long long f=1,w=0;
    char ch=0;
    while(ch<'0'||ch>'9')
    {
        if(ch=='-')
            f=-1;
        ch=getchar();
    }
    while(ch>='0'&&ch<='9')
    {
        w=(w<<1)+(w<<3)+ch-'0';
        ch=getchar();
    }
    return f*w;
}
Matrix operator * (Matrix x,Matrix y)
{
    Matrix z;
    for(long long i=1;i<=4;i++)
        for(long long j=1;j<=4;j++)
            for(long long k=1;k<=4;k++)
                (((z.a[i][k]+=x.a[i][j]*y.a[j][k])%=mod)+=mod)%=mod;
    return z;
}
Matrix ksm(Matrix x,long long y)
{
    Matrix z;
    z.a[1][1]=z.a[2][2]=z.a[3][3]=z.a[4][4]=1;
    while(y)
    {
        if(y&1)
            z=z*x;
        x=x*x;
        y>>=1;
    }
    return z;
}
int main()
{
    G.a[1][1]=1;
    G.a[1][2]=5;
    G.a[1][3]=1;
    G.a[1][4]=-1;
    G.a[2][1]=1;
    G.a[3][2]=1;
    G.a[4][3]=1;
    F.a[1][1]=36;
    F.a[2][1]=11;
    F.a[3][1]=5;
    F.a[4][1]=1;
    while(scanf("%lld",&n)!=EOF)
        if(n<=4)
            printf("%lld\n",F.a[5-n][1]);
        else
            printf("%lld\n",(ksm(G,n-4)*F).a[1][1]);
    return 0;
}
View Code

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!