【LG4841】城市規劃
阿新 • • 發佈:2019-02-10
規劃 聯通圖 ++ 組合數 swa int http 城市規劃 href
【LG4841】城市規劃
題面
洛谷
題解
記\(t_i\)表示\(i\)個點的無向圖個數,顯然\(t_i=2^{C_i^2}\)。
設\(f_i\)表示\(i\)個點的無向連通圖個數,容斥一下,枚舉\(1\)號點所在連通塊的大小,再讓剩下的點隨便構成聯通圖,
則有:
\[ f_i=t_i-\sum_{j=1}^{i-1}f_j*C_{i-1}^{j-1}*t_{i-j} \]
展開組合數:
\[ f_i=t_i-\sum_{j=1}^{i-1}f_j*t_{i-j}*\frac {(i-1)!}{(i-j)!(j-1)!}\\Leftrightarrow \frac {f_i}{(i-1)!}=\frac {t_i}{(i-1)!}-\sum_{j=1}^{i-1}\frac {f_j}{(j-1)!}*\frac {t_{i-j}}{(i-j)!} \]
設\(g_i=\frac {f_i}{(i-1)!},h_i=\frac {t_i}{i!}\),那麽
\[ g_i=i*h_i-\sum_{j=1}^{i-1}g_i*h_i \]
分治+\(NTT\)即可。
代碼
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <cmath> #include <algorithm> using namespace std; const int Mod = 1004535809; int fpow(int x, int y) { int res = 1; while (y) { if (y & 1) res = 1ll * res * x % Mod; x = 1ll * x * x % Mod; y >>= 1; } return res; } const int G = 3, iG = fpow(G, Mod - 2); const int MAX_N = 4e5 + 5; int Limit, rev[MAX_N]; void NTT(int *p, int op) { for (int i = 0; i < Limit; i++) if (i < rev[i]) swap(p[i], p[rev[i]]); for (int i = 1; i < Limit; i <<= 1) { int rot = fpow(op == 1 ? G : iG, (Mod - 1) / (i << 1)); for (int j = 0; j < Limit; j += (i << 1)) { int w = 1; for (int k = 0; k < i; k++, w = 1ll * w * rot % Mod) { int x = p[j + k], y = 1ll * w * p[i + j + k] % Mod; p[j + k] = (x + y) % Mod, p[i + j + k] = (x - y + Mod) % Mod; } } } if (op == -1) { int inv = fpow(Limit, Mod - 2); for (int i = 0; i < Limit; i++) p[i] = 1ll * p[i] * inv % Mod; } } int g[MAX_N], h[MAX_N]; void Div(int l, int r) { if (l == r) return ; static int A[MAX_N], B[MAX_N], C[MAX_N]; int mid = (l + r) >> 1; Div(l, mid); int p = 0; for (Limit = 1; Limit <= (r - l) * 2; Limit <<= 1, ++p) ; for (int i = 0; i < Limit; i++) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (p - 1)); for (int i = 0; i <= mid - l; i++) A[i] = g[i + l]; for (int i = 0; i < r - l; i++) B[i] = h[i + 1]; for (int i = mid - l + 1; i < Limit; i++) A[i] = 0; for (int i = r - l; i < Limit; i++) B[i] = 0; NTT(A, 1); NTT(B, 1); for (int i = 0; i < Limit; i++) C[i] = 1ll * A[i] * B[i] % Mod; NTT(C, -1); for (int i = mid + 1; i <= r; i++) g[i] = (g[i] - C[i - 1 - l] + Mod) % Mod; Div(mid + 1, r); } int N, fac[MAX_N], ifc[MAX_N]; int C(int n, int m) { if (m > n) return 0; else return 1ll * fac[n] * ifc[m] % Mod * ifc[n - m] % Mod; } int main () { #ifndef ONLINE_JUDGE freopen("cpp.in", "r", stdin); #endif cin >> N; fac[0] = 1; for (int i = 1; i <= N; i++) fac[i] = 1ll * fac[i - 1] * i % Mod; ifc[N] = fpow(fac[N], Mod - 2); for (int i = N - 1; ~i; i--) ifc[i] = 1ll * ifc[i + 1] * (i + 1) % Mod; for (int i = 1; i <= N; i++) h[i] = 1ll * fpow(2, 1ll * i * (i - 1) / 2 % (Mod - 1)) * ifc[i] % Mod; for (int i = 1; i <= N; i++) g[i] = 1ll * ifc[i - 1] * fpow(2, 1ll * i * (i - 1) / 2 % (Mod - 1)) % Mod; Div(1, N); printf("%d\n", (int)(1ll * g[N] * fac[N - 1] % Mod)); return 0; }
【LG4841】城市規劃