版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lvzelong2014/article/details/85308591
bzoj3456: 城市规划
分析
方法1:算二次法
考虑一张
点的有标号无向图的个数,显然一共
条边,所以方案数是
设
表示
个点的无向连通图,一种计数的套路是枚举标号为1的点的所在联通快大小,得到
这是一个卷积的形式
令
那么有
多项式求逆即可。
方法1:指数生成函数
具体可以看这里
搞出
的EGF
搞出
的EGF
根据指数生成函数的集合划分意义,可以得到
然后
所以多项式求ln即可
具体方法是
然后
求导->多项式求逆->积分即可。
式子退出来是和方法1一样样的
代码
#include<bits/stdc++.h>
const int N = 524288, P = 1004535809;
int ri() {
char c = getchar(); int x = 0, f = 1; for(;c < '0' || c > '9'; c = getchar()) if(c == '-') f = -1;
for(;c >= '0' && c <= '9'; c = getchar()) x = (x << 1) + (x << 3) - '0' + c; return x * f;
}
int fix(int x) {return (x >> 31 & P) + x;}
int add(int a, int b) {return a += b, a >= P ? a - P : a;}
int mul(int a, int b) {return 1LL * a * b % P;}
int Pow(int x, int k) {
int r = 1;
for(;k; x = mul(x, x), k >>= 1)
if(k & 1)
r = mul(r, x);
return r;
}
int Inv(int x) {return Pow(x, P - 2);}
int n, L, InvL, R[N], w[N], f[N], g[N], G[N], F[N], dG[N];
namespace NTT {
void Pre(int m) {
int x = 0; L = 1;
for(;(L <<= 1) < m; ++x) ;
for(int i = 1;i < L; ++i)
R[i] = R[i >> 1] >> 1 | (i & 1) << x;
int wn = Pow(3, (P - 1) / L); w[0] = 1;
for(int i = 1;i < L; ++i)
w[i] = mul(w[i - 1], wn);
InvL = Inv(L);
}
void DFT(int *F) {
for(int i = 0;i < L; ++i)
if(i < R[i])
std::swap(F[i], F[R[i]]);
for(int i = 1, d = L >> 1; i < L; i <<= 1, d >>= 1)
for(int j = 0;j < L; j += i << 1) {
int *l = F + j, *r = F + j + i, *p = w, tp;
for(int k = i;k--; ++l, ++r, p += d)
tp = mul(*r, *p), *r = fix(*l - tp), *l = add(*l, tp);
}
}
}
void Inv(const int A[], int *B, int n) {
static int C[N];
B[0] = Inv(A[0]); int m = 2;
for(; m >> 1 < n; m <<= 1) {
NTT::Pre(m << 1);
for(int i = 0;i < m; ++i)
C[i] = A[i], C[i + m] = B[i + m] = 0;
NTT::DFT(C); NTT::DFT(B);
for(int i = 0;i < L; ++i)
C[i] = mul(fix(2 - mul(C[i], B[i])), B[i]);
NTT::DFT(C);
for(int i = 0;i < m; ++i)
B[i] = mul(C[L - i & L - 1], InvL), B[i + m] = 0;
}
}
void Pre(int n) {
f[0] = 1; for(int i = 1;i <= n; ++i) f[i] = mul(f[i - 1], i);
g[n] = Inv(f[n]); for(int i = n; i; --i) g[i - 1] = mul(g[i], i);
}
int main() {
Pre(n = ri()); G[1] = 1;
for(int i = 0;i <= n; ++i)
G[i] = mul(Pow(2, (1LL * i * (i - 1) >> 1) % (P - 1)), g[i]);
for(int i = 1;i <= n; ++i)
dG[i - 1] = mul(G[i], i);
Inv(G, F, n + 1);
Pre((n << 1) + 1);
NTT::DFT(dG); NTT::DFT(F);
for(int i = 0;i < L; ++i)
F[i] = mul(F[i], dG[i]);
NTT::DFT(F);
printf("%d\n", mul(mul(F[L - n + 1 & L - 1], InvL), f[n - 1]));
return 0;
}