3456: 城市规划
Time Limit: 40 Sec Memory Limit: 256 MBSubmit: 475 Solved: 273
[ Submit][ Status][ Discuss]
Description
刚刚解决完电力网络的问题, 阿狸又被领导的任务给难住了.
刚才说过, 阿狸的国家有n个城市, 现在国家需要在某些城市对之间建立一些贸易路线, 使得整个国家的任意两个城市都直接或间接的连通. 为了省钱, 每两个城市之间最多只能有一条直接的贸易路径. 对于两个建立路线的方案, 如果存在一个城市对, 在两个方案中是否建立路线不一样, 那么这两个方案就是不同的, 否则就是相同的. 现在你需要求出一共有多少不同的方案.
好了, 这就是困扰阿狸的问题. 换句话说, 你需要求出n个点的简单(无重边无自环)无向连通图数目.
由于这个数字可能非常大, 你只需要输出方案数mod 1004535809(479 * 2 ^ 21 + 1)即可.
Input
仅一行一个整数n(<=130000)
Output
仅一行一个整数, 为方案数 mod 1004535809.
Sample Input
3
Sample Output
4
HINT
对于 100%的数据, n <= 130000
Source
#include<iostream>
#include<cstdio>
#include<queue>
#include<vector>
#include<bitset>
#include<algorithm>
#include<cstring>
#include<map>
#include<stack>
#include<set>
#include<cmath>
#include<ext/pb_ds/priority_queue.hpp>
using namespace std;
const int maxn = 1<<18;
typedef long long LL;
const LL mo = 1004535809;
int n,N,L,rev[maxn],Num[maxn];
LL g[maxn],inv[maxn],C[maxn],fac[maxn],F[maxn]
,G[maxn],b[maxn],c[maxn];
LL ksm(LL x,LL y)
{
LL ret = 1;
for (; y; y >>= 1LL) {
if (y&1LL) ret = ret*x%mo;
x = x*x%mo;
}
return ret;
}
void Pre_Work()
{
LL tot = 1,sum = 2;
C[0] = C[1] = 1;
for (int i = 2; i <= n; i++) {
tot = tot*sum%mo;
sum = 2LL*sum%mo;
C[i] = tot;
}
fac[0] = 1;
for (int i = 1; i <= n; i++)
fac[i] = 1LL*i*fac[i-1]%mo;
inv[n] = ksm(fac[n],mo-2);
for (int i = n - 1; i >= 0; i--)
inv[i] = 1LL*(i+1)*inv[i+1]%mo;
g[0] = g[N] = 1;
g[1] = ksm(3,(mo-1)/N);
for (int i = 2; i < N; i++)
g[i] = g[i-1]*g[1]%mo;
}
void Rader(LL *a,int len)
{
int j = len>>1;
for (int i = 1; i < len - 1; i++) {
if (i < j) swap(a[i],a[j]);
int k = len>>1;
while (j >= k) {
j -= k;
k >>= 1;
}
j += k;
}
}
void NTT(LL *a,int len,int on)
{
Rader(a,len);
for (int k = 2; k <= len; k <<= 1)
for (int i = 0; i < len; i += k) {
int pos = 0;
for (int j = i; j < i + (k>>1); j++) {
LL u = a[j];
LL w = g[pos]*a[j+(k>>1)]%mo;
a[j] = (u+w)%mo;
a[j+(k>>1)] = (u-w+mo)%mo;
pos += (N/k);
}
}
if (on == -1) {
LL INV = ksm(len,mo-2);
for (int i = 0; i < len; i++)
a[i] *= INV,a[i] %= mo;
}
}
void Rev()
{
for (int i = 0; i <= (N>>1); i++)
swap(g[i],g[N-i]);
}
void Inv(int deg,int len)
{
if (deg == 1) {
b[0] = ksm(G[0],mo-2);
return;
}
Inv((deg+1)>>1,len>>1);
for (int i = 0; i < deg; i++) c[i] = G[i];
for (int i = deg; i < len; i++) c[i] = 0;
NTT(b,len,1);
NTT(c,len,1);
for (int i = 0; i < len; i++)
b[i] = (2LL - c[i]*b[i]%mo + mo)*b[i]%mo;
Rev();
NTT(b,len,-1); Rev();
for (int i = deg; i < N; i++) b[i] = 0;
}
int main()
{
#ifdef DMC
freopen("DMC.txt","r",stdin);
#endif
cin >> n;
for (N = 1; N <= n; N <<= 1,++L);
N <<= 1; ++L;
Pre_Work();
for (int i = 0; i < n; i++)
G[i] = C[i]*inv[i]%mo;
Inv(n+1,N);
for (int i = 1; i <= n; i++)
F[i] = C[i]*inv[i-1]%mo;
NTT(b,N,1); NTT(F,N,1);
for (int i = 0; i < N; i++)
F[i] = b[i]*F[i]%mo;
Rev(); NTT(F,N,-1);
cout << F[n]*fac[n-1]%mo;
return 0;
}