生活随笔
收集整理的這篇文章主要介紹了
#3456. 城市规划(生成函数,多项式求逆)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
#3456. 城市規劃
設fnf_nfn?為nnn個點的的點的簡單無向連通圖數目,gng_ngn?為nnn個點的簡單無向圖個數(不要求聯通)。
對于gng_ngn?顯然有gn=2n(n?1)2g_n = 2 ^{\frac{n(n - 1)}{2}}gn?=22n(n?1)?,共有n(n+1)2\frac{n(n + 1)}{2}2n(n+1)?條邊,然后每條邊可選可不選。
我們枚舉111所在的點的連通塊可得:
gn=∑i=1nCn?1i?1fign?i2(2n)=∑i=1n(i?1n?1)fi2(2n?i)2(2n)=∑i=1n(n?1)!(i?1)!(n?i)!fi2(2n?i)2(2n)(n?1)!=∑i=1nfi(i?1)!2(2n?i)(n?i)!設G(x)=∑n=1∞2(2n)(n?1)!xnF(x)=∑n=1∞fn(n?1)!H(x)=∑n=0∞2(2n)n!G(x)=F(x)H(x)F(x)=G(x)H?1(x)構造多項式,多項式求逆,把[xn]項系數乘上(n?1)!即是答案g_n = \sum\limits_{i = 1} ^{n}C_{n - 1} ^{i - 1}f_ig_{n - i}\\ 2 ^{(_2 ^ n)} = \sum_{i = 1} ^{n}(_{i - 1} ^{n - 1})f_i 2 ^{(_2 ^{n - i})}\\ 2 ^{(_2 ^ n)} = \sum_{i = 1} ^{n} \frac{(n - 1)!}{(i - 1)!(n - i)!} f_i 2 ^{(_2 ^{n - i})}\\ \frac{2 ^{(_2 ^ n)}}{(n - 1)!} = \sum_{i = 1} ^{n} \frac{f_i}{(i - 1)!} \frac{2^{(_2 ^{n - i})}}{(n - i)!}\\ 設G(x) = \sum_{n = 1} ^{\infty} \frac{2 ^{(_2 ^n)}}{(n - 1)!} x ^ n\\ F(x) = \sum_{n = 1} ^{\infty} \frac{f_n}{(n - 1)!}\\ H(x) = \sum_{n = 0} ^{\infty} \frac{2 ^{(_2 ^n)}}{n!}\\ G(x) = F(x) H(x)\\ F(x) = G(x)H^{-1}(x)\\ 構造多項式,多項式求逆,把[x ^ n]項系數乘上(n - 1)!即是答案\\ gn?=i=1∑n?Cn?1i?1?fi?gn?i?2(2n?)=i=1∑n?(i?1n?1?)fi?2(2n?i?)2(2n?)=i=1∑n?(i?1)!(n?i)!(n?1)!?fi?2(2n?i?)(n?1)!2(2n?)?=i=1∑n?(i?1)!fi??(n?i)!2(2n?i?)?設G(x)=n=1∑∞?(n?1)!2(2n?)?xnF(x)=n=1∑∞?(n?1)!fn??H(x)=n=0∑∞?n!2(2n?)?G(x)=F(x)H(x)F(x)=G(x)H?1(x)構造多項式,多項式求逆,把[xn]項系數乘上(n?1)!即是答案
#include <bits/stdc++.h>using namespace std
;const int mod
= 1004535809, inv2
= mod
+ 1 >> 1;namespace Quadratic_residue
{struct Complex
{int r
, i
;Complex(int _r
= 0, int _i
= 0) : r(_r
), i(_i
) {}};int I2
;Complex
operator * (const Complex
&a
, Complex
&b
) {return Complex((1ll * a
.r
* b
.r
% mod
+ 1ll * a
.i
* b
.i
% mod
* I2
% mod
) % mod
, (1ll * a
.r
* b
.i
% mod
+ 1ll * a
.i
* b
.r
% mod
) % mod
);}Complex
quick_pow(Complex a
, int n
) {Complex ans
= Complex(1, 0);while (n
) {if (n
& 1) {ans
= ans
* a
;}a
= a
* a
;n
>>= 1;}return ans
;}int get_residue(int n
) {mt19937
e(233);if (n
== 0) {return 0;}if(quick_pow(n
, (mod
- 1) >> 1).r
== mod
- 1) {return -1;}uniform_int_distribution
<int> r(0, mod
- 1);int a
= r(e
);while(quick_pow((1ll * a
* a
% mod
- n
+ mod
) % mod
, (mod
- 1) >> 1).r
== 1) {a
= r(e
);}I2
= (1ll * a
* a
% mod
- n
+ mod
) % mod
;int x
= quick_pow(Complex(a
, 1), (mod
+ 1) >> 1).r
, y
= mod
- x
;if(x
> y
) swap(x
, y
);return x
;}
}const int N
= 1e6 + 10;int r
[N
], inv
[N
], b
[N
], c
[N
], d
[N
], e
[N
], t
[N
];int quick_pow(int a
, int n
) {int ans
= 1;while (n
) {if (n
& 1) {ans
= 1ll * a
* ans
% mod
;}a
= 1ll * a
* a
% mod
;n
>>= 1;}return ans
;
}void get_r(int lim
) {for (int i
= 0; i
< lim
; i
++) {r
[i
] = (i
& 1) * (lim
>> 1) + (r
[i
>> 1] >> 1);}
}void get_inv(int n
) {inv
[1] = 1;for (int i
= 2; i
<= n
; i
++) {inv
[i
] = 1ll * (mod
- mod
/ i
) * inv
[mod
% i
] % mod
;}
}void NTT(int *f
, int lim
, int rev
) {for (int i
= 0; i
< lim
; i
++) {if (i
< r
[i
]) {swap(f
[i
], f
[r
[i
]]);}}for (int mid
= 1; mid
< lim
; mid
<<= 1) {int wn
= quick_pow(3, (mod
- 1) / (mid
<< 1));for (int len
= mid
<< 1, cur
= 0; cur
< lim
; cur
+= len
) {int w
= 1;for (int k
= 0; k
< mid
; k
++, w
= 1ll * w
* wn
% mod
) {int x
= f
[cur
+ k
], y
= 1ll * w
* f
[cur
+ mid
+ k
] % mod
;f
[cur
+ k
] = (x
+ y
) % mod
, f
[cur
+ mid
+ k
] = (x
- y
+ mod
) % mod
;}}}if (rev
== -1) {int inv
= quick_pow(lim
, mod
- 2);reverse(f
+ 1, f
+ lim
);for (int i
= 0; i
< lim
; i
++) {f
[i
] = 1ll * f
[i
] * inv
% mod
;}}
}void polyinv(int *f
, int *g
, int n
) {if (n
== 1) {g
[0] = quick_pow(f
[0], mod
- 2);return ;}polyinv(f
, g
, n
+ 1 >> 1);for (int i
= 0; i
< n
; i
++) {t
[i
] = f
[i
];}int lim
= 1;while (lim
< 2 * n
) {lim
<<= 1;}get_r(lim
);NTT(t
, lim
, 1);NTT(g
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {int cur
= (2 - 1ll * g
[i
] * t
[i
] % mod
+ mod
) % mod
;g
[i
] = 1ll * g
[i
] * cur
% mod
;t
[i
] = 0;}NTT(g
, lim
, -1);for (int i
= n
; i
< lim
; i
++) {g
[i
] = 0;}
}void polysqrt(int *f
, int *g
, int n
) {if (n
== 1) {g
[0] = Quadratic_residue
::get_residue(f
[0]);return ;}polysqrt(f
, g
, n
+ 1 >> 1);polyinv(g
, b
, n
);int lim
= 1;while (lim
< 2 * n
) {lim
<<= 1;}get_r(lim
);for (int i
= 0; i
< n
; i
++) {t
[i
] = f
[i
];}NTT(g
, lim
, 1);NTT(b
, lim
, 1);NTT(t
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {g
[i
] = (1ll * inv2
* g
[i
] % mod
+ 1ll * inv2
* b
[i
] % mod
* t
[i
] % mod
) % mod
;b
[i
] = t
[i
] = 0;}NTT(g
, lim
, -1);for (int i
= n
; i
< lim
; i
++) {g
[i
] = 0;}
}void derivative(int *a
, int *b
, int n
) {for (int i
= 0; i
< n
; i
++) {b
[i
] = 1ll * a
[i
+ 1] * (i
+ 1) % mod
;}
}void integrate(int *a
, int n
) {for (int i
= n
- 1; i
>= 1; i
--) {a
[i
] = 1ll * a
[i
- 1] * inv
[i
] % mod
;}a
[0] = 0;
}void polyln(int *f
, int *g
, int n
) {polyinv(f
, b
, n
);derivative(f
, g
, n
);int lim
= 1;while (lim
< 2 * n
) {lim
<<= 1;}get_r(lim
);NTT(g
, lim
, 1);NTT(b
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {g
[i
] = 1ll * g
[i
] * b
[i
] % mod
;b
[i
] = 0;}NTT(g
, lim
, -1);for (int i
= n
; i
< lim
; i
++) {g
[i
] = 0;}integrate(g
, n
);
}void polyexp(int *f
, int *g
, int n
) {if (n
== 1) {g
[0] = 1;return ;}polyexp(f
, g
, n
+ 1 >> 1);int lim
= 1;while (lim
< 2 * n
) {lim
<<= 1;}polyln(g
, d
, n
);for (int i
= 0; i
< n
; i
++) {t
[i
] = (f
[i
] - d
[i
] + mod
) % mod
;}t
[0] = (t
[0] + 1) % mod
;get_r(lim
);NTT(g
, lim
, 1);NTT(t
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {g
[i
] = 1ll * g
[i
] * t
[i
] % mod
;t
[i
] = d
[i
] = 0;}NTT(g
, lim
, -1);for (int i
= n
; i
< lim
; i
++) {g
[i
] = 0;}
}int h
[N
], g
[N
], fac
[N
], ifac
[N
], n
;void init() {fac
[0] = 1;for (int i
= 1; i
< N
; i
++) {fac
[i
] = 1ll * i
* fac
[i
- 1] % mod
;}ifac
[N
- 1] = quick_pow(fac
[N
- 1], mod
- 2);for (int i
= N
- 2; i
>= 0; i
--) {ifac
[i
] = 1ll * ifac
[i
+ 1] * (i
+ 1) % mod
;}
}int main() {scanf("%d", &n
);init();for (int i
= 1; i
<= n
; i
++) {g
[i
] = 1ll * quick_pow(2, 1ll * i
* (i
- 1) / 2 % (mod
- 1)) * ifac
[i
- 1] % mod
;}for (int i
= 0; i
<= n
; i
++) {h
[i
] = 1ll * quick_pow(2, 1ll * i
* (i
- 1) / 2 % (mod
- 1)) * ifac
[i
] % mod
;}polyinv(h
, b
, n
+ 1);for (int i
= 0; i
<= n
; i
++) {h
[i
] = b
[i
];b
[i
] = 0;}int lim
= 1;while (lim
<= 2 * n
) {lim
<<= 1;}get_r(lim
);NTT(g
, lim
, 1);NTT(h
, lim
, 1);for (int i
= 0; i
< lim
; i
++) {g
[i
] = 1ll * g
[i
] * h
[i
] % mod
;h
[i
] = 0;}NTT(g
, lim
, -1);printf("%d\n", 1ll * g
[n
] * fac
[n
- 1] % mod
);return 0;
}
總結
以上是生活随笔為你收集整理的#3456. 城市规划(生成函数,多项式求逆)的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。