题面
首先考虑假如填了连续的两个数a,b均>=2,那么后面的数一定全是b。先暂时不考虑这种情况。
考虑假如填了一个>=2的数a,那么后面a个数都必须填1,之后才能自由填,于是设计状态f[i]表示从i开始可以自由填的方案数。那么假设上一个自由填>=2的数是d,那么f[i]+=f[i-d-1],假如上一个自由填的是1,f[i]+=f[i-1],总之不能转移i-2就是了。
但考虑到有一些>=2的a使得要到n之后的某个位置才能自由填,所以上述第一种转移要转移到2*n,第二种转移到n即可(后面的重复了)。
在考虑连续两个>=2的情况,考虑这两个填的位置,只需要把f[1]~f[n-2]乘上(n-1)*(n-1)加到答案中即可。
代码:
#include<iostream>
#include<cstdio>
#define ll long long
#define up(a,b) a=(a+b)%mod
using namespace std;
const int mod=1000000007;
const int maxn=2000100;
int n;
ll f[maxn],s[maxn],ans=0;
int main()
{
scanf("%d",&n);
f[0]=s[0]=1;
for(int i=1;i<=2*n;i++)
{
int l=max(0,i-n-1),r=min(n-1,i-3);
if(l<=r) f[i]=(s[r]-(l==0?0:s[l-1])+mod)%mod;
if(i<=n) up(f[i],f[i-1]);
s[i]=(s[i-1]+f[i])%mod;
}
for(int i=n;i<=2*n;i++)
up(ans,f[i]);
for(int i=0;i<=n-2;i++)
up(ans,f[i]*(n-1)%mod*(n-1)%mod);
printf("%lld",ans);
return 0;
}