RiverSheepSHEEP
Processing math: 100%

[集训队作业2013]城市规划

奔跑的心634·2023-03-15 21:50·32 次阅读

[集训队作业2013]城市规划

P4841 [集训队作业2013]城市规划#

套路题,设fi表示无标号联通图方案数,设gi表示无标号图方案数,易得gi=2(n2)
考虑固定 1

gn=ni=1(n1i1)figni

将组合数拆开化成EGF的形式

2(n2)(n1)!=ifi(i1)!2(ni2)(ni)!

显然的卷积形式 H=FG,所以F=HG1
最后答案为 n![xn]F,多项式求逆即可。

Code
Copy
#include<cstdio> #include<iostream> #include<cstring> #define IN inline #define LL long long using namespace std; const int N = 2e5 + 5, P = 1004535809, G = 3; int n, m, a[N << 2], b[N << 2], inv[N], pw[N]; LL fpow(LL x, LL y) { LL res = 1; for (; x; x >>= 1, y = y * y % P) if (x & 1) res = res * y % P; return res; } namespace Poly{ int rev[N << 2], insF[N << 2], sginv[N << 2]; void NTT(int *f, int len, int fl) { if (len == 1) return; for (int i = 0; i < len; i++) if (i < rev[i]) swap(f[i], f[rev[i]]); for (int l = 1; l < len; l <<= 1) { int I = fpow((P - 1) / (l << 1), G); if (fl == -1) I = fpow(P - 2, I); for (int i = 0; i < len; i += (l << 1)) { int W = 1; for (int j = 0; j < l; j++, W = (LL)W * I % P) { int x = f[i + j], y = (LL)f[i + j + l] * W % P; f[i + j] = (x + y) % P, f[i + j + l] = (x - y + P) % P; } } } } void Mulpoly(int *f, int *g, int lenF, int lenG) { int len = 1, bit = 0; while (len <= lenF + lenG) len <<= 1, bit++; for (int i = 1; i < len; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1); NTT(f, len, 1), NTT(g, len, 1); for (int i = 0; i < len; i++) f[i] = (LL)f[i] * g[i] % P; NTT(f, len, -1); int IV = fpow(P - 2, len); for (int i = 0; i <= lenF + lenG; i++) f[i] = (LL)f[i] * IV % P; for (int i = lenF + lenG + 1; i < len; i++) f[i] = 0; } void Invpoly(int *f, int lenF, int *g) { // [0, lenF) static int Flen[100]; int cnt = 0; for (int i = lenF; i > 1; i = i + 1 >> 1) Flen[++cnt] = i; for (int i = 1; i <= (cnt >> 1); i++) swap(Flen[i], Flen[cnt - i + 1]); g[0] = fpow(P - 2, f[0]), Flen[0] = 1; for (int j = 1; j <= cnt; j++) { int len = 1, bit = 0; while (len < (Flen[j] << 1)) len <<= 1, bit++; for (int i = 1; i < len; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << bit - 1); for (int i = Flen[j - 1]; i < len; i++) g[i] = 0; for (int i = 0; i < Flen[j]; i++) insF[i] = f[i]; for (int i = Flen[j]; i < len; i++) insF[i] = 0; NTT(g, len, 1), NTT(insF, len, 1); for (int i = 0; i < len; i++) g[i] = (LL)g[i] * (2LL - (LL)insF[i] * g[i] % P + P) % P; NTT(g, len, -1); int IV = fpow(P - 2, len); for (int i = 0; i < Flen[j]; i++) g[i] = (LL)g[i] * IV % P; } } void Getsginv(int len) { sginv[0] = sginv[1] = 1; for (int i = 2; i <= len; i++) sginv[i] = (LL)sginv[P % i] * (P - P / i) % P; } void Dpoly(int *f, int lenF) { for (int i = 0; i < lenF; i++) f[i] = (LL)f[i + 1] * (i + 1) % P; } void Jfpoly(int *f, int lenF) { for (int i = lenF; i >= 0; i--) f[i + 1] = (LL)f[i] * sginv[i + 1] % P; f[0] = 0; } void Lnpoly(int *f, int lenF) { // [0, lenF) static int Inv_f[N << 2]; Invpoly(f, lenF, Inv_f), Dpoly(f, lenF - 1), Mulpoly(f, Inv_f, lenF - 1, lenF - 1), Jfpoly(f, lenF - 1); for (int i = lenF; i <= (lenF << 1); i++) f[i] = 0; } void Exppoly(int *f, int lenF, int *g) { static int s[N << 2]; int limit = 1; while (limit < lenF) limit <<= 1; g[0] = 1; for (int len = 2; len <= limit; len <<= 1) { for (int i = 0; i < (len >> 1); i++) s[i] = g[i]; for (int i = (len >> 1); i < len; i++) s[i] = 0; Lnpoly(s, len); for (int i = 0; i < len; i++) s[i] = (f[i] - s[i] + P) % P; s[0] = (s[0] + 1) % P; Mulpoly(g, s, len - 1, len - 1); for (int i = len; i < (len << 1); i++) g[i] = 0; } for (int i = lenF; i < limit; i++) g[i] = 0; for (int i = 0; i < limit; i++) s[i] = 0; } } IN int read() { int t = 0,res = 0; char ch = getchar(); for (; !isdigit(ch); ch = getchar()) t |= (ch == '-'); for (; isdigit(ch); ch = getchar()) res = (res << 3) + (res << 1) + (ch ^ 48); return t ? -res : res; } int main() { n = read(), Poly::Getsginv(n), inv[0] = inv[1] = 1; for (int i = 2; i <= n; i++) inv[i] = (LL)inv[i - 1] * Poly::sginv[i] % P; for (int i = 0; i <= n; i++) pw[i] = fpow(((LL)i * (i - 1LL) / 2LL) % (P - 1), 2LL); for (int i = 0; i <= n; i++) a[i] = (LL)pw[i] * inv[i] % P; Poly::Invpoly(a, n + 1, b), memset(a, 0, sizeof a); for (int i = 1; i <= n; i++) a[i] = (LL)pw[i] * inv[i - 1] % P; Poly::Mulpoly(a, b, n, n); int ans = a[n]; for (int i = 1; i < n; i++) ans = (LL)ans * i % P; printf("%d\n", ans); }
posted @   RiverSheep  阅读(32)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
目录