参考:https://www.cnblogs.com/2016gdgzoi509/p/8999460.html

列出生成函数方程,g(x)是价值x的个数

\[f(x)=g(x)*f^2(x)+1
\]

+1是f[0]=1

根据公式解出

\[f(x)=\frac{1+(-)\sqrt{1-4*g(x)}}{2*g(x)}
\]

舍去+的答案,分式上下同乘\( 1-\sqrt{1-4*g(x)} \)

\[f(x)=\frac{2}{1+\sqrt{1-4*g(x)}}
\]

然后套多项式开跟和求逆的板子即可

  1. #include<iostream>
  2. #include<cstdio>
  3. #include<cstring>
  4. #include<cmath>
  5. using namespace std;
  6. const int N=500005,mod=998244353,inv2=499122177;
  7. int n,m,bt,lm,re[N],a[N],b[N],c[N],t[N];//,aa[N],bb[N],cc[N];
  8. int read()
  9. {
  10. int r=0,f=1;
  11. char p=getchar();
  12. while(p>'9'||p<'0')
  13. {
  14. if(p=='-')
  15. f=-1;
  16. p=getchar();
  17. }
  18. while(p>='0'&&p<='9')
  19. {
  20. r=r*10+p-48;
  21. p=getchar();
  22. }
  23. return r*f;
  24. }
  25. int ksm(int a,int b)
  26. {
  27. int r=1;
  28. while(b)
  29. {
  30. if(b&1)
  31. r=1ll*r*a%mod;
  32. a=1ll*a*a%mod;
  33. b>>=1;
  34. }
  35. return r;
  36. }
  37. void dft(int a[],int f,int lm)
  38. {
  39. // for(int i=0;i<lm;i++)
  40. // cerr<<a[i]<<" ";cerr<<endl;
  41. // bt=log2(lm);//cerr<<" "<<lm<<" "<<bt<<endl;
  42. // for(int i=0;i<lm;i++)
  43. // re[i]=(re[i>>1]>>1)|((i&1)<<(bt-1));
  44. for(int i=0;i<lm;i++)
  45. if(i<re[i])
  46. swap(a[i],a[re[i]]);
  47. for(int i=1;i<lm;i<<=1)
  48. {
  49. int wi=ksm(3,(mod-1)/(i*2));
  50. if(f==-1)
  51. wi=ksm(wi,mod-2);
  52. for(int k=0;k<lm;k+=(i<<1))
  53. {
  54. int w=1,x,y;
  55. for(int j=0;j<i;j++)
  56. {
  57. x=a[j+k],y=1ll*w*a[i+j+k]%mod;
  58. a[j+k]=(x+y)%mod,a[i+j+k]=(x-y+mod)%mod;
  59. w=1ll*w*wi%mod;
  60. }
  61. }
  62. }
  63. if(f==-1)
  64. {
  65. int ni=ksm(lm,mod-2);
  66. for(int i=0;i<lm;i++)
  67. a[i]=1ll*a[i]*ni%mod;
  68. }
  69. // for(int i=0;i<lm;i++)
  70. // cerr<<a[i]<<" ";cerr<<endl<<endl;;
  71. }
  72. void qiuni(int len)
  73. {
  74. if(len==1)
  75. {
  76. c[0]=ksm(b[0],mod-2);
  77. return;
  78. }
  79. qiuni(len>>1);
  80. memcpy(t,b,sizeof(int)*len);
  81. memset(t+len,0,sizeof(int)*len);
  82. int bt=-1,lm=1;
  83. while(lm<len<<1)
  84. lm<<=1,bt++;
  85. for(int i=0;i<lm;i++)
  86. re[i]=(re[i>>1]>>1)|((i&1)<<bt);
  87. dft(t,1,lm);
  88. dft(c,1,lm);
  89. for(int i=0;i<lm;i++)
  90. c[i]=1ll*c[i]*(2-1ll*t[i]*c[i]%mod+mod)%mod;
  91. dft(c,-1,lm);
  92. memset(c+len,0,sizeof(int)*len);
  93. }
  94. void kaigen(int len)
  95. {
  96. if(len==1)
  97. {
  98. b[0]=1;
  99. return;
  100. }
  101. kaigen(len>>1);
  102. memset(c,0,sizeof(int)*len);
  103. qiuni(len);
  104. memcpy(t,a,sizeof(int)*len);
  105. memset(t+len,0,sizeof(int)*len);
  106. int bt=-1,lm=1;
  107. while(lm<len<<1)
  108. lm<<=1,bt++;
  109. for(int i=0;i<lm;i++)
  110. re[i]=(re[i>>1]>>1)|((i&1)<<bt);
  111. dft(t,1,lm);
  112. dft(b,1,lm);
  113. dft(c,1,lm);
  114. for(int i=0;i<len*2;i++)
  115. b[i]=1ll*(1ll*b[i]*b[i]+t[i])%mod*c[i]%mod*inv2%mod;
  116. dft(b,-1,lm);
  117. memset(b+len,0,sizeof(int)*len);
  118. }
  119. int main()
  120. {
  121. n=read(),m=read();
  122. for(int i=1;i<=n;i++)
  123. {
  124. int x=read();
  125. a[x]++;
  126. }
  127. for(int i=1;i<=m;i++)
  128. a[i]=(-a[i]*4+mod)%mod;
  129. for(bt=1;(1<<bt)<=m;bt++);
  130. lm=(1<<bt);
  131. for(int i=0;i<lm;i++)
  132. if(a[i])
  133. a[i]=mod-4;
  134. a[0]++;
  135. kaigen(lm);
  136. // for(int i=0;i<n;i++)
  137. // cerr<<a[i]<<" "<<b[i]<<" "<<c[i]<<endl;
  138. b[0]=(b[0]+1)%mod;
  139. memset(c,0,sizeof(c));
  140. qiuni(lm);
  141. for(int i=1;i<=m;i++)
  142. printf("%d\n",c[i]*2%mod);
  143. return 0;
  144. }

bzoj 3625: [Codeforces Round #250]小朋友和二叉树【NTT+多项式开根求逆】的更多相关文章

  1. BZOJ 3625 [Codeforces Round #250]小朋友和二叉树 ——NTT 多项式求逆 多项式开根

    生成函数又有奇妙的性质. $F(x)=C(x)*F(x)*F(x)+1$ 然后大力解方程,得到一个带根号的式子. 多项式开根有解只与常数项有关. 发现两个解只有一个是成立的. 然后多项式开根.求逆. ...

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

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

  3. [BZOJ3625][Codeforces Round #250]小朋友和二叉树 多项式开根+求逆

    https://www.lydsy.com/JudgeOnline/problem.php?id=3625 愉快地列式子.设\(F[i]\)表示权值为\(i\) 的子树的方案数,\(A[i]\)为\( ...

  4. BZOJ3625 [Codeforces Round #250]小朋友和二叉树(生成函数+多项式开根)

    设f(n)为权值为n的神犇二叉树个数.考虑如何递推求这个东西. 套路地枚举根节点的左右子树.则f(n)=Σf(i)f(n-i-cj),cj即根的权值.卷积的形式,cj也可以通过卷上一个多项式枚举.可以 ...

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

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

  6. BZOJ3625: [Codeforces Round #250]小朋友和二叉树

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

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

    题目描述: bzoj luogu 题解: 生成函数ntt. 显然这种二叉树应该暴力薅掉树根然后分裂成两棵子树. 所以$f(x)= \sum_{i \in c} \sum _{j=0}^{x-c} f( ...

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

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

  9. Codeforces Round #250 (Div. 1)E. The Child and Binary Tree

    题意:有一个集合,求有多少形态不同的二叉树满足每个点的权值都属于这个集合并且总点权等于i 题解:先用生成函数搞出来\(f(x)=f(x)^2*c(x)+1\) 然后转化一下变成\(f(x)=\frac ...

随机推荐

  1. oracle 静默安装

    下载oracle的安装包: 下载地址: 注意下载oracle是须要注冊oracle的 http://download.oracle.com/otn/nt/oracle11g 下载两个包: linux. ...

  2. IE 扩展调用主窗体中的函数

    IE 扩展调用主窗体中的函数 在函数名前加上 parentWindow 就可以.如: <script>     var doc = external.menuArguments.docum ...

  3. Android 平板中 自己定义键盘(popuwindow) 居于屏幕左下方 仿微信的password输入界面

          之前博客中,介绍过使用谷歌提供的键盘的一些api,能够非常好地自己定义键盘,參考我之前的博客链接:android 自己定义键盘 ,这个有一个局限性,仅仅能占满屏幕,无法做到仅仅能占一部分的 ...

  4. vue的安装以及语法介绍

    #需要用到一个vue文件,还有一个自己的js文件main.js<!DOCTYPE html> <html lang="en"> <head> & ...

  5. unity视频播放,

    PC端视频播放: Unity中实现PC端播放视频,非常easy用到MovieTexture属于贴图Texture的子类. 在播放视频之前.我们得记得下载quicktime插件,仅仅有导入了quickt ...

  6. 《STL源代码剖析》---stl_deque.h阅读笔记(2)

    看完,<STL源代码剖析>---stl_deque.h阅读笔记(1)后.再看代码: G++ 2.91.57,cygnus\cygwin-b20\include\g++\stl_deque. ...

  7. EF(Entity Framework)通用DBHelper通用类,增删改查以及列表

    其中 通用类名:DBhelper 实体类:UserInfo 1 //新增 2 DBHelper<UserInfo> dbhelper = new DBHelper<UserInfo& ...

  8. NIO原理图

  9. 教你如何配置Ubuntu用于高效、高质量的发送邮件

    本文首发在: http://mengxi.me/how-to-setup-ubuntu-sendmail-to-deliver-email-fast-and-reliable/ 在网站上线后,经常会遇 ...

  10. 将异常(getStackTrace)转化成String

    方法一: private static String getStackMsg(Exception e) { StringBuffer sb = new StringBuffer(); StackTra ...