zoukankan      html  css  js  c++  java
  • 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

  • 相关阅读:
    107. Binary Tree Level Order Traversal II
    108. Convert Sorted Array to Binary Search Tree
    111. Minimum Depth of Binary Tree
    49. Group Anagrams
    使用MALTAB标定实践记录
    442. Find All Duplicates in an Array
    522. Longest Uncommon Subsequence II
    354. Russian Doll Envelopes
    opencv 小任务3 灰度直方图
    opencv 小任务2 灰度
  • 原文地址:https://www.cnblogs.com/ghostcai/p/15177413.html
Copyright © 2011-2022 走看看