版权声明:转吧转吧这条东西只是来搞笑的。。 https://blog.csdn.net/jpwang8/article/details/89313202
Description
给定n和p
对于i从1到n,求n个点形成的,从1出发最长路恰好为i的竞赛图数量,对p取模
Solution
由一些小常识可以知道,竞赛图一定存在一条哈密顿路径,且强连通分量缩点之后形成的,一定是一条若干scc形成的链,拓扑序小的scc向后连满边
也就是说,1为起点的最长路,一定是从1出发,向后走完所有scc。所以最长路=n-[1走不到的点]
考虑设f[n]表示n个节点的答案,g[n]表示n个点形成竞赛图强连通的方案。推g可以容斥
考虑怎么求f,我们枚举1所在scc的大小i,然后枚举1能到达其余scc的大小之和j,那么答案就是
Code
#include <stdio.h>
#include <string.h>
#include <algorithm>
#define rep(i,st,ed) for (int i=st;i<=ed;++i)
typedef long long LL;
const int N=2005;
LL f[N],g[N],ans[N];
LL C[N][N]; int MOD;
LL ksm(LL x,LL dep) {
LL res=1;
for (;dep;dep>>=1,x=x*x%MOD) {
(dep&1)?(res=res*x%MOD):0;
}
return res;
}
void upd(LL &x,LL v) {
x+=v,(x>=MOD)?(x-=MOD):0;
}
int main(void) {
// freopen("data.in","r",stdin);
// freopen("myp.out","w",stdout);
int n; scanf("%d%d",&n,&MOD);
C[0][0]=1;
rep(i,1,n) {
C[i][0]=C[i][i]=1;
rep(j,1,i-1) C[i][j]=(C[i-1][j-1]+C[i-1][j])%MOD;
}
f[0]=g[0]=1;
rep(i,1,n) {
f[i]=g[i]=ksm(2,i*(i-1)/2);
rep(j,1,i-1) {
g[i]=(g[i]+MOD-f[j]*g[i-j]%MOD*C[i][j]%MOD)%MOD;
}
}
rep(i,1,n) rep(j,0,n-i) {
upd(ans[i+j],g[i]*C[n-1][i-1]%MOD*C[n-i][j]%MOD*f[j]%MOD);
}
rep(i,1,n) printf("%lld ", (ans[i]*f[n-i]%MOD+MOD)%MOD); puts("");
return 0;
}