2020/5/10 模拟赛 Day6 T2 操场
Description
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; }