题意
n≤500000n≤500000
分析
实际上就是对于每个ii,求有多少大小为的置换满足不存在大小为11的轮换且存在大小为的轮换。
考虑用容斥来求ansiansi,设f[i]f[i]表示长度为ii的错排数量,枚举大小为的轮换个数jj不难得到
复杂度为O(nlogn)O(nlogn)
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
typedef long long LL;
const int N=500005;
const int MOD=1000000007;
int n,jc[N],ny[N],f[N];
int C(int n,int m)
{
return (LL)jc[n]*ny[m]%MOD*ny[n-m]%MOD;
}
int main()
{
scanf("%d",&n);
jc[0]=jc[1]=ny[0]=ny[1]=1;
for (int i=2;i<=n;i++) jc[i]=(LL)jc[i-1]*i%MOD,ny[i]=(LL)(MOD-MOD/i)*ny[MOD%i]%MOD;
for (int i=2;i<=n;i++) ny[i]=(LL)ny[i-1]*ny[i]%MOD;
f[0]=f[2]=1;
for (int i=3;i<=n;i++) f[i]=(LL)(i-1)*(f[i-1]+f[i-2])%MOD;
int ans=0;
for (int i=2;i<=n;i++)
{
int w=1;
for (int j=1;j*i<=n;j++)
{
w=(LL)w*C(n-i*(j-1),i)%MOD*jc[i-1]%MOD;
if (j&1) (ans+=(LL)w*f[n-i*j]%MOD*ny[j]%MOD)%=MOD;
else (ans+=MOD-(LL)w*f[n-i*j]%MOD*ny[j]%MOD)%=MOD;
}
}
printf("%d",ans);
return 0;
}