心态崩了 不放传送门了 辣鸡bz

还是正经一点写一下题解= =

就是显然我们可以把权值写成生成函数形式g(0/1序列)来表示权值是否出现

然后f来表示总的方案数

可以列出 分别枚举左右子树和空树的情况

然后解方程得到

显然开根开出来常数项是1 而g不带常数项 那么就必须取-才能保证除法有效

然后为了计算方便我们把柿子写成(平方差上下同乘)

然后就是多项式开根和多项式求逆了

多项式求逆可以戳我的【学习笔记】

然后开根是类似的 也是通过倍增 可以得到递归求解就好了

这个最可怕的是所以是随便套 就非常恐怖了(囧

然后我就发现我的写法写多项式开根非常麻烦 然后就开始胡乱改

常数上天 BZT飞

本来写的心态就很不好 懒得改了= =

所以这份代码BZ是会T掉的 小心食用qwq

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #include<cmath>
  5. #define ll long long
  6. #define inf 20021225
  7. #define wph 998244353
  8. #define G 3
  9. #define mxn 1600010
  10. #define inv2 499122177
  11. #define int ll
  12. using namespace std;
  13. int rev[mxn],inv;
  14. int ksm(int bs,int mi)
  15. {
  16. int ans=1;
  17. while(mi)
  18. {
  19. if(mi&1) ans=(ll)ans*bs%wph;
  20. bs=(ll)bs*bs%wph; mi>>=1;
  21. }
  22. return ans;
  23. }
  24. int init(int n)
  25. {
  26. int lim=1,l=0;
  27. while(lim<n) lim<<=1,l++;
  28. for(int i=0;i<lim;i++)
  29. rev[i] = (rev[i>>1]>>1)|((i&1)<<(l-1));
  30. inv = ksm(lim,wph-2);
  31. return lim;
  32. }
  33. void ntt(int *a,int n,int f)
  34. {
  35. for(int i=0;i<n;i++)
  36. if(rev[i]>i) swap(a[i],a[rev[i]]);
  37. for(int k=2;k<=n;k<<=1)
  38. {
  39. int Wn=ksm(G,(wph-1)/k),mid=k>>1;
  40. if(f) Wn=ksm(Wn,wph-2);
  41. for(int w=1,i=0;i<n;i+=k,w=1)
  42. {
  43. for(int j=0;j<mid;j++,w=(ll)w*Wn%wph)
  44. {
  45. int x=a[i+j],y=(ll)w*a[i+j+mid]%wph;
  46. a[i+j]=(x+y)%wph;a[i+j+mid]=(x-y+wph)%wph;
  47. }
  48. }
  49. }
  50. if(f) for(int i=0;i<n;i++) a[i]=(ll)a[i]*inv%wph;
  51. }
  52. int f[mxn],g[mxn],h[mxn];
  53. void poly_inv(int *a,int n)
  54. {
  55. if(n==1)
  56. {
  57. g[0] = ksm(a[0],wph-2);
  58. return;
  59. }
  60. int mid = (n+1)>>1;
  61. poly_inv(a,mid);
  62. int lim = init(n<<1);
  63. for(int i=0;i<n;i++) h[i]=a[i];
  64. for(int i=n;i<lim;i++) h[i]=0;
  65. ntt(h,lim,0); ntt(g,lim,0);
  66. for(int i=0;i<lim;i++)
  67. g[i] = (2ll - (ll)h[i]*g[i]%wph + wph)%wph *g[i] %wph;
  68. ntt(g,lim,1);
  69. for(int i=n;i<lim;i++) g[i]=0;
  70. }
  71. int d[mxn],t[mxn];
  72. void poly_sqrt(int a[],int n)
  73. {
  74. //printf("%d\n",n);
  75. if(n==1){d[0] = 1;return;}
  76. int mid = n>>1; poly_sqrt(a,mid);
  77. int lim = init(n);// while(lim<(n<<1)) lim<<=1;
  78. memset(g,0ll,sizeof(ll)*n*2);
  79. poly_inv(d,n);
  80. for(int i=0;i<n;i++) h[i]=a[i];
  81. for(int i=n;i<lim*2;i++) h[i]=0;
  82. lim = init(n<<1);
  83. ntt(h,lim,0); ntt(g,lim,0); ntt(d,lim,0);
  84. for(int i=0;i<lim;i++)
  85. d[i] = ((ll)h[i]*g[i]%wph + d[i])%wph *inv2%wph;
  86. ntt(d,lim,1);
  87. for(int i=n;i<lim;i++) d[i]=0;
  88. }
  89. int a[mxn];
  90. signed main()
  91. {
  92. int n,m,x;
  93. scanf("%lld%lld",&n,&m);
  94. for(int i=1;i<=n;i++)
  95. {
  96. scanf("%lld",&x);
  97. if(x<=m) f[x] = wph - 4;
  98. }
  99. f[0]=1;
  100. int lim=init(m<<1);
  101. poly_sqrt(f,lim);
  102. d[0]++;
  103. //for(int i=0;i<(m<<1);i++) printf("%d ",d[i]);
  104. memset(g,0,sizeof(g));
  105. lim = init(m<<1);
  106. poly_inv(d,lim);// printf("%d ",g[0]*2%wph);
  107. for(int i=1;i<=m;i++) printf("%lld\n",g[i]*2%wph);
  108. /**scanf("%d",&n);
  109. for(int i=0;i<n;i++) scanf("%d",&f[i]);
  110. poly_inv(f,n);
  111. for(int i=0;i<n;i++) printf("%d ",g[i]);*/
  112. return 0;
  113. }
  114. /**
  115. */

BZOJ3625 CF438E 小朋友与二叉树的更多相关文章

  1. [BZOJ3625][CF438E]小朋友和二叉树

    题面 Description 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\ldots,c_n\).如果一棵带点权的有根二叉树满足其 ...

  2. [BZOJ3625][CF438E]小朋友和二叉树 (多项式开根,求逆)

    题面 题解 设多项式的第a项为权值和为a的二叉树个数,多项式的第a项表示是否为真,即 则,所以F是三个多项式的卷积,其中包括自己: ,1是F的常数项,即. 我们发现这是一个一元二次方程,可以求出,因为 ...

  3. [CF438E] 小朋友和二叉树

    Description 给定一个整数集合 \(c\),对于每个 \(i\in[1,m]\),求有多少种不同的带点权的二叉树使得这棵树点权和为 \(i\) 并且顶点的点权全部在集合 \(c\) 中.\( ...

  4. 【bzoj3625】【xsy1729】小朋友和二叉树

    [bzoj3625]小朋友与二叉树 题意 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. 考虑一个含有n个互异正整数的序列c[1],c[2],...,c[n].如果一棵带点权的有根二叉树满足其所有 ...

  5. 【BZOJ3625/CF438E】小朋友和二叉树(多项式求逆,多项式开方)

    [BZOJ3625/CF438E]小朋友和二叉树(多项式求逆,多项式开方) 题面 BZOJ CodeForces 大致题意: 对于每个数出现的次数对应的多项式\(A(x)\) 求\[f(x)=\fra ...

  6. 【CF438E】小朋友和二叉树 解题报告

    [CF438E]小朋友和二叉树 Description ​ 我们的小朋友很喜欢计算机科学,而且尤其喜欢二叉树. ​ 考虑一个含有\(n\)个互异正整数的序列\(c_1,c_2,\dots,c_n\). ...

  7. BZOJ 3625: [Codeforces Round #250]小朋友和二叉树

    3625: [Codeforces Round #250]小朋友和二叉树 Time Limit: 40 Sec  Memory Limit: 256 MBSubmit: 304  Solved: 13 ...

  8. 「BZOJ 3645」小朋友与二叉树

    「BZOJ 3645」小朋友与二叉树 解题思路 令 \(G(x)\) 为关于可选大小集合的生成函数,即 \[ G(x)=\sum[i\in c ] x^i \] 令 \(F(x)\) 第 \(n\) ...

  9. [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆)

    [BZOJ 3625] [Codeforces 438E] 小朋友的二叉树 (DP+生成函数+多项式开根+多项式求逆) 题面 一棵二叉树的所有点的点权都是给定的集合中的一个数. 让你求出1到m中所有权 ...

随机推荐

  1. 【HDOJ6666】Quailty and CCPC(模拟)

    题意:给出罚时现场赛的题数和罚时,问是否有在金牌线下取整被卡出,四舍五入卡入的队伍 n<=1e5 思路: #include<bits/stdc++.h> using namespac ...

  2. laravel的使用

    1.先下载composer.phar 下载地址:https://getcomposer.org/download/ 把composer.phar拷贝到自己的项目目录中,执行以下代码: php comp ...

  3. 常用的Android关键词定位方法

    1字符串,特征字 根据程序运行中出现的特征字词进行搜索,从而获取定位到程序的相关位置之中.以前用 得比较多,不过现在一般难以找到想要的关键词.有时候需要对特征字进行拆分来进行搜索.才 能获得一点提示. ...

  4. 121、TensorFlow张量命名

    # tf.Graph对象定义了一个命名空间对于它自身包含的tf.Operation对象 # TensorFlow自动选择一个独一无二的名字,对于数据流图中的每一个操作 # 但是给操作添加一个描述性的名 ...

  5. 从零开始创建 symfony-cmf

    前提: 官方 https://symfony.com/doc/master/cmf/quick_tour/the_big_picture.html#setting-up-the-database 由于 ...

  6. 设计模式 - 装饰器模式(Decorator)

    简介 场景 通过继承和关联都可以给对象增加行为,区别如下: 继承是静态的(无法在程序运行时动态扩展),且作用于所有子类.硬编码,高耦合. 通过装饰器可以在运行时添加行为和属性到指定对象.关联关系就是在 ...

  7. Vagrant 入门 - 项目设置

    原文地址 配置 Vagrant 项目的第一步是创建 Vagrantfile 文件.Vagrantfile 文件的目的有两个: 设置项目的根目录.Vagrant 中的许多配置选项是相对于这个根目录的. ...

  8. 第 11 章 python线程与多线程

    一.什么是线程 在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程. 进程只是用来把资源集中到一起(进程只是一个资源单位,或者说资源集合),而线程才是cpu上的执行单位. 多线程(即多 ...

  9. Vue过渡:用Velocity实现JavaScript钩子

    Velocity is an animation engine with a similar API to jQuery's $.animate(). It has no dependencies, ...

  10. [Linux] 002 预备知识

    1. 开源软件 (1) 常见开源软件 Apache NGINXTM MySQL PHP Saamba mongoDB Python Ruby Sphinx -- (2) 开源软件的特点 绝大多数开源软 ...