test20200430 最长路径
最长路径
在Byteland一共有\(n\)个城市,编号依次为\(1\)到\(n\),它们之间计划修建\(\binom{n}{2}\)条单向道路,对于任意两个不同的点\(i\)和\(j\),在它们之间有且仅有一条单向道路,方向要么是\(i\)到\(j\),要么是\(j\)到\(i\)。换句话说,这是一个\(n\)个点的竞赛图。
Byteasar居住在\(1\)号城市,他希望从\(1\)号城市出发,沿着单向道路不重复地访问一些城市,使得访问的城市数尽可能多。
请写一个程序,帮助Byteasar计算有多少种道路修建方式,使得从\(1\)号点出发的最长简单路径经过点数恰好为\(k\),由于答案可能很大,请对\(P\)取模输出。
题解
竞赛图一定存在哈密顿路径。
对于\(n\)个点的竞赛图,\(1\)号点能作为哈密顿路径起点的充要条件是\(1\)能到剩余\(n-1\)个点。
考虑归纳证明,\(n=1,2\)时显然成立。对于\(n\geq 3\)的情况,显然\(1\)能到剩余\(n-1\)个点是必要的,不然何谈哈密顿路径。证明充分性考虑构造,我们\(1\)至少能到剩余\(n-1\)个点导出子图的所有哈密顿路径的起点中至少一个,不然与假设矛盾。证毕。
所以这道题要让最长路为\(k\)只需要让\(1\)能到\(k\)个点,其余\(n-k\)个点不能到即可。
设\(f_n\)为\(1\)能作为哈密顿路径起点的\(n\)个点的竞赛图数量,\(g_n=2^{\binom{n}{2}}\)。
最后有\(\text{ans}_k=\binom{n-1}{k-1}f_kg_{n-k}\)。时间复杂度\(O(n^2)\)。
CO int N=2e3+10;
int C[N][N],G[N],F[N];
int main(){
int n=read<int>(),P=read<int>();
for(int i=0;i<=n;++i){
C[i][0]=1;
for(int j=1;j<=i;++j) C[i][j]=(C[i-1][j-1]+C[i-1][j])%P;
}
for(int i=0;i<=n;++i) G[i]=fpow(2,i*(i-1)/2,P);
for(int i=1;i<=n;++i){
F[i]=G[i];
for(int j=1;j<=i-1;++j) F[i]=(F[i]+P-(int64)C[i-1][j-1]*F[j]%P*G[i-j]%P)%P;
}
for(int i=1;i<=n;++i){
int ans=(int64)C[n-1][i-1]*F[i]%P*G[n-i]%P;
printf("%d\n",ans);
}
return 0;
}
然后是老生常谈的生成函数优化。其实这个式子跟有标号连通无向图的一模一样。
时间复杂度\(O(n\log n)\)。