题意
n≤500000
n
≤
500000
分析
实际上就是对于每个
i
i
,求有多少大小为的置换满足不存在大小为
1
1
的轮换且存在大小为的轮换。
考虑用容斥来求
ansi
a
n
s
i
,设
f[i]
f
[
i
]
表示长度为
i
i
的错排数量,枚举大小为的轮换个数
j
j
不难得到
复杂度为 O(nlogn) O ( n l o g n )
代码
#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;
}