求n個點的帶標號連通簡單圖的個數。答案對1004535809取模。
n<=130000
根據套路,首先我們需要求出n個點的帶標號簡單圖的個數,設為g[n]
顯然我們有g[n]=2^(n*(n-1)/2)
考慮設答案為f[n],要怎麼求出?
列舉1號點所在的聯通塊的大小,我們可以知道 g[
n]=∑
i=1n
f[i]
ci−1
n−1g
[n−i
] 因為f是保證聯通的所以不會算重
把g帶入,c拆開 2n
∗(n+
1)/2
=∑i=
1nf[
i](n
−1)!
(i−1
)!(n
−i)!
2(n−
i)∗(
n−i−
1)/2
兩邊同除(n-1)! 2n
∗(n+
1)/2
(n−1
)!=∑
i=1n
f[i]
(i−1
)!2(
n−i)
∗(n−
i−1)
/2(n
−i)!
可以發現這是乙個卷積的形式
那麼我們就直接上fft就好了
需要多項式求逆
第一次寫寫的很醜qwq
#include
#include
#include
#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;
typedef double db;
ll read()
void write(int
x) char ch[20];int tot=0;
for(;x;x/=10) ch[++tot]=x
%10+'0';
fd(i,tot,1) putchar(ch[i]);
puts("");
}const int mo=1004535809,d=3,n=5
*1e5+5;
int pwr(int
x,ll y)
int n,len,lg,inv,t[n],a[n],b[n],c[n],w[n];
int p[n],h[n],g[n],f[n];
void pre(int len)
void dft(int *a,int len,int lg,int flag)
for(int
m=2;m
<=len;m
<<=1) }}
for(int i=0;iif (flag==-1) for(int i=0;i*inv
%mo;
}void ntt(int
*a,int
*b,int
*c,int len,int lg)
for(int i=0;i*2);
ntt(p,b,h,len*2,lg+1);
for(int i=0;i*2;i++) h[i]=mo-h[i];
(h[0]+=2)%=mo;
ntt(h,b,b,len*2,lg+1);
for(int i=len;i*2;i++) b[i]=0;
} }int fact[n],inv[n],f[n],g[n],inv_g[n],h[n];
int main()
upd:聽說一次倍增只需要3次dft qwq
結果我常數直接*2壓倒性劣勢
集訓隊作業 城市規劃
點這裡看題目。考慮如下遞推 f i i 個點的無向有標號連通圖的個數。g i i 個點的無向有標號圖的個數。以下給出兩種計算方式。不難看出乙個式子 g n sum n binomf ig 這相當於列舉 1 所在的連通塊大小,然後構造出這個連通塊,剩下的點任意連。然後感覺這個東西非常的 egf 就嘗試...
P4841 集訓隊作業2013 城市規劃
設 f i 表示 i 個點的無向連通圖個數,g i 表示 i 個點的無向圖個數。列舉 1 所在連通塊的大小,有 g i sum limits ic f jg 化簡得 g i sum limits i fracf jg frac sum limits i frac frac 設 f i frac,g ...
P4841 集訓隊作業2013 城市規劃 題解
求 n 個點的有標號的無向連通圖數目。text 1 le n le1.3 times10 5 我們設 g i 表示有 i 個點的有標號無向圖數目,易得 g i 2 考慮列舉每兩個點之間是否連通。設 f i 表示有 i 個點的連通圖數目 即答案所求 則可得 g n sum n c f i g 考慮 1...