Description
太长了自己看
相信各位打过Hello 2018的dalao都知道题意我就不多讲了。
Solution
这道题比赛时没想真是亏了。。。
首先根据一些竞赛图相关姿势我们知道汉密尔顿回路唯一且一定存在,那么这个条件就没有用了
然后让我们来慢慢套路。
首先设Fn表示n个点的答案,枚举n所在的强联通分量的大小,我们可以得到:
F[n]=∑i=1n(F[n−i]+F[i]+i∗(i−1)2+(n−i)∗i)∗G[i]∗Cp[n][i]
G[i]表示i个点内部打成强联通分量的概率
Cp[n][i]表示从n个点中输出i个点的概率(输的点之间不互相计算)
接下来考虑G[n]如何计算,直接计算可能比较麻烦,我们可以考虑容斥,枚举n所在的强联通分量的大小
G[n]=1−∑i=1n−1G[i]∗Cp[n][i]
那么我们只需要考虑如何求解Cp[n][m]了,考虑新加入一个点是否被输出来
Cp[n][m]=Cp[n−1][m]∗(1−p)m+Cp[n−1][m−1]∗pn−m
然后这道题就做完了,真是满满的计数题的套路23333
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long ll;
const int N=2*1e3+5,Mo=998244353;
int pwr(int x,int y) {
int z=1;
for(;y;y>>=1,x=(ll)x*x%Mo)
if (y&1) z=(ll)z*x%Mo;
return z;
}
int n,a,b,p,q,P[N],Q[N],Cp[N][N],G[N],F[N];
int main() {
scanf("%d",&n);
scanf("%d%d",&a,&b);
int p=(ll)a*pwr(b,Mo-2)%Mo,q=Mo+1-p;
P[0]=1;fo(i,1,n) P[i]=(ll)P[i-1]*p%Mo;
Q[0]=1;fo(i,1,n) Q[i]=(ll)Q[i-1]*q%Mo;
Cp[0][0]=1;
fo(i,1,n) {
Cp[i][0]=1;
fo(j,1,i) Cp[i][j]=((ll)Cp[i-1][j]*Q[j]%Mo+(ll)Cp[i-1][j-1]*P[i-j]%Mo)%Mo;
}
G[1]=1;
fo(i,2,n) {
G[i]=1;
fo(j,1,i-1) (G[i]+=Mo-(ll)G[j]*Cp[i][j]%Mo)%=Mo;
}
F[1]=0;
fo(i,2,n) {
fo(j,1,i-1) {
int now=0;
(now+=F[i-j]+F[j])%=Mo;
(now+=j*(j-1)/2)%=Mo;
(now+=(i-j)*j)%=Mo;
(F[i]+=(ll)now*G[j]%Mo*Cp[i][j]%Mo)%=Mo;
}
(F[i]+=(ll)i*(i-1)/2*G[i]%Mo*Cp[i][i]%Mo)%=Mo;
F[i]=(ll)F[i]*pwr(1+Mo-(ll)G[i]*Cp[i][i]%Mo,Mo-2)%Mo;
}
printf("%d\n",F[n]);
return 0;
}