新生赛出这题真可了
翻转卡片
题目链接
状态表示
f[i][j][0/1]
表示前前i张牌选择完毕,反转了j次,第i张是反面或者正面
状态转移
分别对应0101
1001
这两种情况
f[i][j][1]+=(f[i-2][j-1][1]+f[i-3][j-1][1])
f[i][j][0]+=(f[i-1][j][1])
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const LL mod = 1000000007;
const int N = 1005;
LL f[N][N][2];//f[i][j][0/1]表示前前i张牌选择完毕,反转了j次,第i张是反面或者正面
LL fac[N];
LL qmi(LL a,LL b)
{
LL res=1;
while(b)
{
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int main()
{
fac[1]=1;
for(int i=2;i<N;i++)fac[i]=fac[i-1]*i%mod;
f[1][1][1]=1;
f[2][1][0]=1;f[2][1][1]=1;
for(int i=3;i<N;i++)
{
for(int j=1;j<N;j++)
{
//也可以这样写
//f[i][j][1]=(f[i][j][1]+f[i-1][j-1][0]+f[i-3][j-1][1])%mod;
f[i][j][1]=(f[i][j][1]+f[i-2][j-1][1]+f[i-3][j-1][1])%mod;
f[i][j][0]=(f[i][j][0]+f[i-1][j][1])%mod;
}
}
int T;
cin>>T;
while(T--)
{
int n;
cin>>n;
LL up=0,down=0;
for(int i=1;i<=n;i++)
{
LL sum=(f[n][i][0]+f[n][i][1])%mod*fac[i]%mod;
up=(up+sum*i%mod)%mod;
down=(down+sum)%mod;
}
cout<<up*qmi(down,mod-2)%mod<<endl;
}
}