传送门:bzoj5219
题解
竞赛图性质:
- 必然存在一条哈密尔顿路径
- 缩点之后按拓扑序形成一条“链”
由竞赛图性质得到从点1出发的最长路径上点数等于1所在 s c c scc scc点数+拓扑序在1(链中靠后)的 s c c scc scc的点的总数。
f [ n ] f[n] f[n]表示有 n n n个节点的竞赛图的个数,显然: f [ n ] = 2 n ( n − 1 ) 2 f[n]=2^{\frac{n(n-1)}{2}} f[n]=22n(n−1)。
g
[
n
]
g[n]
g[n]表示有
n
n
n个节点的竞赛图强连通分量,考虑枚举拓扑序最小的
s
c
c
scc
scc进行容斥:
g
[
n
]
=
f
[
n
]
−
∑
i
=
1
n
−
1
(
n
i
)
g
[
i
]
f
[
n
−
i
]
g[n]=f[n]-\sum\limits_{i=1}^{n-1}\binom {n}{i}g[i]f[n-i]
g[n]=f[n]−i=1∑n−1(in)g[i]f[n−i]
初始 f [ 0 ] = 1 , g [ 1 ] = 1 f[0]=1,g[1]=1 f[0]=1,g[1]=1,其余递推得到。
a n s [ n ] ans[n] ans[n]表示则点1出发最长路径为 n n n的方案数。枚举1所在 s c c scc scc点数以及链中靠后的总点数:
a n s [ n ] = ∑ i = 1 n ( n − 1 i − 1 ) ( n − i j ) g [ i ] f [ j ] f [ n − i − j ] ans[n]=\sum_{i=1}^n\binom{n-1}{i-1}\binom{n-i}{j}g[i]f[j]f[n-i-j] ans[n]=∑i=1n(i−1n−1)(jn−i)g[i]f[j]f[n−i−j]
组合数线性递推预处理即可。
代码
#include<bits/stdc++.h>
#define RI register
using namespace std;
typedef long long ll;
const int N=2020;
int n,mod,c[N][N];
int f[N],g[N],ans[N];
inline int ad(int x,int y){x+=y;return x>=mod?x-mod:x;}
inline int mul(int x,int y){return 1ll*x*y%mod;}
inline int dc(int x,int y){x-=y;return x<0?x+mod:x;}
inline int fp(int x,int y)
{
int re=1;
for(;y;y>>=1,x=mul(x,x))
if(y&1) re=mul(re,x);
return re;
}
int main(){
RI int i,j,res;
scanf("%d%d",&n,&mod);
f[0]=g[1]=1;
for(i=0;i<=n;++i){
c[i][0]=c[i][i]=1;
for(j=1;j<i;++j)
c[i][j]=ad(c[i-1][j],c[i-1][j-1]);
}
for(i=1;i<=n;++i) f[i]=fp(2,i*(i-1)/2);
for(i=2;i<=n;++i){
res=0;
for(j=1;j<i;++j)
res=ad(res,mul(c[i][j],mul(g[j],f[i-j])));
g[i]=dc(f[i],res);
}
for(i=1;i<=n;++i){
for(j=n-i;~j;--j)
ans[i+j]=ad(ans[i+j],(ll)c[n-1][i-1]*c[n-i][j]%mod*(ll)f[j]%mod*(ll)g[i]%mod*(ll)f[n-i-j]%mod);
}
for(i=1;i<=n;++i) printf("%d\n",ans[i]);
return 0;
}