• Andrew Stankevich Contest 46 Problem D. Dichromatic Trees


    题意:定义红黑树如下:只有红点和黑点的二叉树,红点的儿子必须为黑点;从根出发到任意一个不足两个儿子的点,经过的黑点个数定义为black height,要求整棵树都有相同的black height。问n个点,black height小于等于H的红黑树种类数,答案对258280327取模

    设F[i][j]表示根节点为红色,包含i个节点,black height为j的红黑树个数

    G[i][j]表示根节点为黑色,包含i个节点,black height为j的红黑树个数
    考虑到红色节点的儿子只能为黑色,且红点不改变black height,那么有

    [ m F[i][j]=sumlimits_{k=0}^{i-1}G[k][j]*G[i-k][j] ]

    同时,黑点的儿子没有限制,红黑均可,且会对black height贡献1,那么有

    [ m G[i][j]=sumlimits_{k=0}^{i-1}(F[k][j-1]+G[k][j-1])*(F[i-k][j-1]+G[i-k][j-1]) ]

    可以发现,F和G的转移类似于卷积的形式,且模数找不到原根,用MTT加速转移H次即可

    #include <bits/stdc++.h>
    #define int long long
    using namespace std;
    
    #define rep(i,x,y) for(int i=x;i<=y;i++)
    
    int rd() {
    	int ret = 0, f = 1;char c;
    	while (c = getchar(), !isdigit(c))f = c == '-' ? -1 : 1;
    	while (isdigit(c))ret = ret * 10 + c - '0', c = getchar();
    	return ret * f;
    }
    
    typedef long long ll;
    typedef long double ld;
    
    const int inf = 1 << 30;
    const int MAXN = 524289+2;
    int MOD = 258280327;
    const int BASE = 1 << 15;
    const ld Pi = acos(-1.0);
    
    struct CP {
    	ld x, y;
    	CP(ld xx = 0, ld yy = 0) {
    		x = xx;
    		y = yy;
    	}
    } P1[MAXN << 2], P2[MAXN << 2], Q[MAXN << 2];
    
    CP operator+(CP a, CP b) {
    	return {a.x + b.x, a.y + b.y};
    }
    
    CP operator-(CP a, CP b) {
    	return {a.x - b.x, a.y - b.y};
    }
    
    CP operator*(CP a, CP b) {
    	return {a.x *b.x - a.y * b.y, a.x *b.y + a.y * b.x};
    }
    
    int limit, r[MAXN << 2];
    
    ll qpow(ll x, ll y) {
    	ll ret = 1, base = x;
    	while (y) {
    		if (y & 1)
    			ret = ret * base % MOD;
    		base = base * base % MOD;
    		y >>= 1;
    	}
    	return ret;
    }
    
    void FFT(CP *A, int type) {
    	for (int i = 0; i < limit; i++)
    		if (i < r[i])
    			swap(A[i], A[r[i]]);
    	for (int mid = 1; mid < limit; mid <<= 1) {
    		CP Wn(cos(Pi / mid), type * sin(Pi / mid));
    		for (int R = mid << 1, j = 0; j < limit; j += R) {
    			CP w(1, 0);
    			for (int k = 0; k < mid; k++, w = w * Wn) {
    				CP x = A[j + k], y = w * A[j + mid + k];
    				A[j + k] = x + y;
    				A[j + mid + k] = x - y;
    			}
    		}
    	}
    }
    
    void init(int n) {
    	limit = 1;
    	while (limit <= n)
    		limit <<= 1;
    	for (int i = 1; i < limit; i++)
    		r[i] = r[i >> 1] >> 1 | ((i & 1) ? limit >> 1 : 0);
    }
    
    
    int MTT(int *a, int *b, int n, int m, int *res, int MOD) {
    //	init(n + m);
    	for (int i = 0; i < n; i++) {
    		P1[i] = {a[i] / BASE, a[i] % BASE};
    		P2[i] = {a[i] / BASE, -a[i] % BASE};
    	}
    	for (int i = n; i < limit; i++)
    		P1[i] = P2[i] = {0, 0};
    	for (int i = 0; i < m; i++)
    		Q[i] = {b[i] / BASE, b[i] % BASE};
    	for (int i = m; i < limit; i++)
    		Q[i] = {0, 0};
    	FFT(P1, 1);
    	FFT(P2, 1);
    	FFT(Q, 1);
    	for (int i = 0; i < limit; i++) {
    		Q[i].x /= limit, Q[i].y /= limit;
    		P1[i] = P1[i] * Q[i], P2[i] = P2[i] * Q[i];
    	}
    
    	FFT(P1, -1);
    	FFT(P2, -1);
    	for (int i = 0; i < n + m - 1; i++) {
    
    		ll a1b1, a1b2, a2b1, a2b2;
    
    		a1b1 = (ll)floor((P1[i].x + P2[i].x) / 2 + 0.5) % MOD;
    
    		a1b2 = (ll)floor((P1[i].y + P2[i].y) / 2 + 0.5) % MOD;
    
    		a2b1 = (ll)floor((P1[i].y - P2[i].y) / 2 + 0.5) % MOD;
    
    		a2b2 = (ll)floor((P2[i].x - P1[i].x) / 2 + 0.5) % MOD;
    
    		res[i] = ((a1b1 * BASE + (a1b2 + a2b1)) * BASE + a2b2) % MOD;
    
    		res[i] = (res[i] + MOD) % MOD;
    	}
    	return n + m - 1;
    }
    
    int B[MAXN * 8], tot;
    
    struct Poly {
    	int *a, len;
    	void init0(int _len) {
    		len = _len;
    		a = B + tot;
    		for (int i = 0; i < len; i++)
    			a[i] = 0;
    		tot += len;
    	}
    	void init(int _len, int *src) {
    		len = _len;
    		a = B + tot;
    		for (int i = 0; i < len; i++)
    			a[i] = src[i];
    		tot += len;
    	}
    	void mul(const Poly &rhs) {
    		len = MTT(a, rhs.a, len, rhs.len, a, MOD);
    	}
    };
    
    const int LEN = 131072+2;
    
    signed main() {
    	freopen("dichromatic.in","r",stdin);
    	freopen("dichromatic.out","w",stdout);
    	int n, hh;
    	cin>>n>>hh;
    	static int F[MAXN], G[MAXN], H[MAXN],tmp[MAXN];
    	static int ans[MAXN];
    	init(LEN+LEN);
    	F[0]=1;
    	F[1]=1;
    	for (int t = 1; t <= hh ; t++) {
    		for (int i = 0; i <= LEN; i++) {
    			H[i] = (F[i] + G[i]) % MOD;
    			ans[i] = (ans[i] + H[i]) % MOD;
    		}
    		MTT(H, H, LEN, LEN, tmp, MOD);
    		rep(i,1,LEN) G[i]=tmp[i-1];
    		MTT(G, G, LEN, LEN, tmp, MOD);
    		rep(i,1,LEN) F[i]=tmp[i-1];
    		F[0]=G[0]=0;
    	}
    	for (int i = 0; i <= LEN; i++) {
    		H[i] = (F[i] + G[i]) % MOD;
    		ans[i] = (ans[i] + H[i]) % MOD;
    	}
    	for(int i=1;i<=n;i++){
    		int xx;
    		cin>>xx;
    		cout<<ans[xx]<<" ";	
    	}	
    }
    

    本文来自博客园,作者:GhostCai,转载请注明原文链接:https://www.cnblogs.com/ghostcai/p/15177413.html

  • 相关阅读:
    redis 笔记
    经验
    增加模块-概念图
    node API buffer
    VS2010中使用CL快速 生成DLL的方法
    WIN7下VS2010中使用cl编译的步骤
    Win7下VS2010编译的程序在XP报错:找不到msvcp100d.dll或者msvcp100.dll
    C#速学
    Windows下架设SVN服务
    Redis 压力测试
  • 原文地址:https://www.cnblogs.com/ghostcai/p/15177413.html
Copyright © 2020-2023  润新知