zoukankan      html  css  js  c++  java
  • 【CF】438E. The Child and Binary Tree

    http://codeforces.com/contest/438/problem/E

    题意:询问每个点权值在 $c_1, c_2, ..., c_m$ 中,总权值和为 $s$ 的二叉树个数。请给出每个$s in [1,S]$ 对应的答案。($S,m < 10^5$)

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=(1e5+10)*4, mo=998244353;
    int two, G[30], nG[30], rev[N];
    int ipow(int a, int b) { int x=1; for(; b; b>>=1, a=(ll)a*a%mo) if(b&1) x=(ll)x*a%mo; return x; }
    void fft_init() {
    	two=ipow(2, mo-2); G[23]=ipow(3, (mo-1)/(1<<23)); nG[23]=ipow(G[23], mo-2);
    	for(int i=22; i; --i) G[i]=(ll)G[i+1]*G[i+1]%mo, nG[i]=(ll)nG[i+1]*nG[i+1]%mo;
    }
    int getlen(int n) {
    	int len=1, bl=-1;
    	for(; len<n; len<<=1, ++bl);
    	for(int i=1; i<len; ++i) rev[i]=(rev[i>>1]>>1)|((i&1)<<bl);
    	return len;
    }
    void fft(int *a, int n, int f) {
    	for(int i=0; i<n; ++i) if(i<rev[i]) swap(a[i], a[rev[i]]);
    	for(int m=2, now=1; m<=n; m<<=1, ++now) {
    		int mid=m>>1, w=1, wn=G[now], u, v; if(f) wn=nG[now];
    		for(int i=0; i<n; i+=m, w=1) 
    			for(int j=0; j<mid; ++j) {
    				u=a[i+j], v=(ll)a[i+j+mid]*w%mo;
    				a[i+j]=(u+v)%mo; a[i+j+mid]=(u-v+mo)%mo; w=(ll)w*wn%mo;
    			}
    	}
    }
    void getinv(int *a, int *b, int n) {
    	if(n==1) { b[0]=ipow(a[0], mo-2); return; }
    	getinv(a, b, (n+1)>>1);
    	static int c[N], d[N];
    	memcpy(c, a, sizeof(int)*(n)); memcpy(d, b, sizeof(int)*((n+1)>>1));
    	int len=getlen(n+n-1), nlen=ipow(len, mo-2);
    	fft(c, len, 0); fft(d, len, 0);
    	for(int i=0; i<len; ++i) d[i]=(ll)d[i]*(2-(ll)d[i]*c[i]%mo+mo)%mo;
    	fft(d, len, 1);
    	for(int i=0; i<n; ++i) b[i]=(ll)d[i]*nlen%mo;
    	memset(c, 0, sizeof(int)*(len)); memset(d, 0, sizeof(int)*(len));
    }
    void getroot(int *a, int *b, int n) {
    	if(n==1) { b[0]=sqrt(a[0]); return; }
    	getroot(a, b, (n+1)>>1);
    	static int c[N], d[N];
    	memcpy(c, a, sizeof(int)*(n));
    	getinv(b, d, n);
    	int len=getlen(n+n-1), nlen=ipow(len, mo-2);
    	fft(c, len, 0); fft(d, len, 0);
    	for(int i=0; i<len; ++i) d[i]=(ll)c[i]*d[i]%mo;
    	fft(d, len, 1);
    	for(int i=0; i<n; ++i) b[i]=(ll)two*((b[i]+(ll)d[i]*nlen%mo)%mo)%mo;
    	memset(d, 0, sizeof(int)*(len)); memset(c, 0, sizeof(int)*(len));
    }
    int a[N], b[N];
    int main() {
    	fft_init();
    	int m, n; scanf("%d%d", &n, &m);
    	for(int i=0; i<n; ++i) { int x; scanf("%d", &x); if(x<=m) a[x]=mo-4; }
    	a[0]=1;
    	getroot(a, b, m+1);
    	b[0]=(b[0]+1)%mo;
    	getinv(b, a, m+1);
    	for(int i=1; i<=m; ++i) printf("%d
    ", (a[i]<<1)%mo);
    	return 0;
    }
    

      

    多项式求根= =具体看picks博客..http://picks.logdown.com/posts/202388-square-root-of-polynomial

    其实想到了母函数然后知道用倍增来求根本题就解决了= =...跪跪跪orz

    一定要注意那些多项式的次数啊!!!一定要想明白啊!!!

  • 相关阅读:
    iOS中Zbar二维码扫描的使用
    SOJ 1135. 飞跃原野
    SOJ 1048.Inverso
    SOJ 1219. 新红黑树
    SOJ 1171. The Game of Efil
    SOJ 1180. Pasting Strings
    1215. 脱离地牢
    1317. Sudoku
    SOJ 1119. Factstone Benchmark
    soj 1099. Packing Passengers
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4365349.html
Copyright © 2011-2022 走看看