luogu P4841 城市规划

luogu P4841 城市规划

题目大意

求出 n 个点的简单 (无重边无自环) 无向连通图数目

题解

一眼发现这个模数有点意思

3是原根

然后可以根据题意写出一个DP

可以获得40‘的好成绩


#include<bits/stdc++.h>
#define int long long
#define mod 1004535809
using namespace std;
int n, c[1005][1005], f[1005], pw[1000005];
signed main(){
	for(int i = 0; i <= 1000; i ++) c[i][0] = 1;
	for(int i = 1; i <= 1000; i ++)
		for(int j = 1; j <= i; j ++)
			c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % mod;
	pw[0] = 1;		
	for(int i = 1; i <= 1000000; i ++) pw[i] = pw[i - 1] * 2 % mod;		
	scanf("%lld", &n);
	f[1] = 1, f[2] = 1;
	for(int i = 3; i <= n; i ++){
		f[i] = pw[i * (i - 1) / 2];
		for(int j = 1; j < i; j ++)
			f[i] = (f[i] - c[i - 1][j - 1] * f[j] % mod * pw[(i - j) * (i - j - 1) / 2] % mod + mod) % mod;
	}
	printf("%lld", f[n]);
	return 0;
}

然后

在这里插入图片描述
发现对G求个逆然后乘一下这题就没了


#include<bits/stdc++.h>
#define int long long
#define mod 1004535809
#define GG 3
#define N 8000005
using namespace std;
int qpow(int x, int y){
	int ret = 1;
	for(; y; y >>= 1, x = x * x % mod) if(y & 1) ret = ret * x % mod;
	return ret;
}
int rev[N], GG_inv, len_inv;
void ntt(int *a, int len, int o){
	len_inv = qpow(len, mod - 2);
	for(int i = 0; i <= len; i ++) rev[i] = (rev[i >> 1] >> 1) | ((i&1) * len >> 1);
	for(int i = 0; i <= len; i ++) if(i < rev[i]) swap(a[i], a[rev[i]]);
	for(int i = 2; i <= len; i <<= 1){
		int wn = qpow((o == 1)? GG:GG_inv, (mod - 1) / i);
		for(int j = 0, p = i / 2; j + i - 1<= len; j += i){
			int w0 = 1;
			for(int k = j; k < j + p; k ++, w0 = w0 * wn % mod){
				int X = a[k], Y = w0 * a[k + p] % mod;
				a[k] = (X + Y) % mod;
				a[k + p] = (X - Y + mod) % mod;
			}
		}
	}
	if(o == -1) 
		for(int i = 0; i <= len; i ++) a[i] = a[i] * len_inv % mod;
}
int c[N];
void inv(int *a, int *b, int sz){
	if(sz == 0) {b[0] = qpow(a[0], mod - 2); return;}
	inv(a, b, sz / 2);
	int len = 1;
	for(; len <= sz + sz; len <<= 1);
	for(int i = 0; i <= sz; i ++) c[i] = a[i];
	for(int i = sz + 1; i <= len; i ++) c[i] = 0;
	ntt(c, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) b[i] = (b[i] * 2 % mod - b[i] * b[i] % mod * c[i] % mod + mod) % mod;
	ntt(b, len, -1);
	for(int i = sz + 1; i <= len; i ++) b[i] = 0;
}
void mul(int *a, int *b, int n, int m){
	int len = 1;
	for(; len <= n + m; len <<= 1);
	ntt(a, len, 1), ntt(b, len, 1);
	for(int i = 0; i <= len; i ++) a[i] = a[i] * b[i] % mod;
	ntt(a, len, -1);
}
int fac[N], F[N], G[N], H[N], G_inv[N], n, m;
signed main(){
	GG_inv = qpow(GG, mod - 2);
	scanf("%lld", &n);
	fac[0] = 1;
	for(int i = 1; i <= n; i ++) fac[i] = fac[i - 1] * i % mod;
	for(int i = 0; i <= n; i ++) H[i] = qpow(2, i * (i - 1) / 2) * qpow(fac[i - 1], mod - 2) % mod;
	for(int i = 0; i <= n; i ++) G[i] = qpow(2, i * (i - 1) / 2) * qpow(fac[i], mod - 2) % mod;
	inv(G, G_inv, n);
	mul(H, G_inv, n, n);
	printf("%lld", H[n] * fac[n - 1] % mod);
	return 0;
}

这也能算黑题???

posted @ 2019-10-03 20:51  lahlah  阅读(24)  评论(0编辑  收藏  举报