这个题明显是需要求递推式,但直接去看比较复杂
可以先打表求出前10个的答案,然后用高斯消元来解递推式(可以暴力打表,或者有人用状压DP)
假设递推式是一个四元方程,至于为什么也不大清楚(可能是操场是4*n的缘故)
然后得到递推式f(n)=f(n-1)+5*f(n-2)+f(n-3)-f(n-4)
因为1<=n<=10^18很大,所以用矩阵快速幂来解递推式,得到答案
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
const ll MOD=1e9+7;
const int N=4;
struct node
{
ll a[10][10];
};
node shu,ans,mp;
//shu是输入的矩阵,ans是所求答案
node matrix(node x,node y)
{
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++){
mp.a[i][j]=0;
for(int p=1;p<=N;p++)
mp.a[i][j]=(mp.a[i][j]+x.a[i][p]*y.a[p][j]+MOD)%MOD;
//矩阵乘法
}
return mp;
}
void work(ll k)
{//矩阵快速幂
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
ans.a[i][j]=0;
for(int i=1;i<=N;i++) ans.a[i][i]=1;
node t=shu;
while(k){
if(k&1)
ans=matrix(ans,t);
k>>=1;
t=matrix(t,t);
}
}
int main()
{
ll n;
for(int i=1;i<=N;i++)
for(int j=1;j<=N;j++)
shu.a[i][j]=0;
shu.a[1][1]=1;
shu.a[1][2]=5;
shu.a[1][3]=1;
shu.a[1][4]=-1;
shu.a[2][1]=1;
shu.a[3][2]=1;
shu.a[4][3]=1;
while(cin>>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
{
work(n-4);
printf("%lld\n",(ans.a[1][1]*36l%MOD+ans.a[1][2]*11l%MOD+ans.a[1][3]*5l%MOD+ans.a[1][4])%MOD);
}
}
return 0;
}
以及暴力打表代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
const int N=1e5+10;
bool vis[4][100];
int ans;
void dfs(int i,int j,int n)
{
if(i==4)
{
ans++;
return;
}
int nj=j+1;
int ni=i;
if(nj==n)
{
nj=0;
ni++;
}
if(vis[i][j]) dfs(ni,nj,n);
else
{
if(j!=n-1&&!vis[i][j+1])
{
vis[i][j]=vis[i][j+1]=true;
dfs(ni,nj,n);
vis[i][j]=vis[i][j+1]=false;
}
if(i!=3&&!vis[i+1][j])
{
vis[i][j]=vis[i+1][j]=true;
dfs(ni,nj,n);
vis[i][j]=vis[i+1][j]=false;
}
}
}
void make_table(int n)
{
for(int i=1;i<=n;i++)
{
ans=0;
dfs(0,0,i);
printf("%d: %d\n",i,ans);
}
}
int main()
{
int n;
scanf("%d",&n);
make_table(n);
return 0;
}