「雅礼集训 2018-04-03」Problem B

求有多少 NN 个的竞赛图包含至少一个长度为 KK 的简单环, 输出答案模 109+710^9+7 的结果。

竞赛图: 任意两个点之间都有一条有向边的图。

简单环: 不经过重复节点的回路。

Constraints

n5000n \leq 5000

Solution

首先有一个定理:竞赛图中如果包含一个大小大于等于 kk 的强连通分量,则这个强连通分量内包含长度为 [3,k][3,k] 的简单环。则问题转化为:求至少有一个强连通分量大小大于等于 kk 的方案数。

pip_{i} 表示 ii 个点的竞赛图方案数,则显然有 pi=2i(i1)2p_{i}=2^{\frac{i\cdot (i-1)}{2}}

gig_{i} 表示 ii 个点的强连通分量且为竞赛图的方案数,则显然有 gi=pij=1i1(ij)gjpijg_{i}=p_{i}-\sum _{j=1}^{i-1}\binom{i}{j}\cdot g_{j}\cdot p_{i-j}

fif_{i} 表示当前用了 ii 个点,不包含大小大于等于kk的强连通分量的方案数。枚举最后一个强连通分量的大小进行转移,可得:

fi=j=1min(k1,i)(ij)gjfijf_{i}=\sum _{j=1}^{min(k-1,i)}\binom{i}{j}\cdot g_{j}\cdot f_{i-j}

则最终答案为 pnfnp_{n}-f_{n} ,时间复杂度 O(n2)O(n^{2})

Code

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include<cstdio>
#include<algorithm>
#include<cstring>
#define LL long long
using namespace std;
const int N=5e3+5;
const int mod=1e9+7;
int n,k,C[N][N],g[N],p[N],f[N];
int power(int a,int b)
{
int ans=1;
while(b)
{
if(b&1)ans=1ll*ans*a%mod;
a=1ll*a*a%mod;b>>=1;
}
return ans;
}
int main()
{
freopen("b.in","r",stdin);
freopen("b.out","w",stdout);
scanf("%d%d",&n,&k);
for(int i=0;i<=n;i++)C[i][0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<=i;j++)
C[i][j]=(C[i-1][j]+C[i-1][j-1])%mod;
for(int i=1;i<=n;i++)p[i]=power(2,i*(i-1)/2);
g[1]=1;
for(int i=3;i<=n;i++)
{
g[i]=p[i];
for(int j=1;j<i;j++)
g[i]=(g[i]-1ll*C[i][j]*g[j]%mod*p[i-j]%mod+mod)%mod;
}
f[0]=1;
for(int i=1;i<=n;i++)
for(int j=1;j<k&&j<=i;j++)
f[i]=(f[i]+1ll*C[i][j]*g[j]%mod*f[i-j])%mod;
printf("%d",(p[n]-f[n]+mod)%mod);
return 0;
}