题目:http://acm.hdu.edu.cn/showproblem.php?pid=5279

令 n 个点的树的 EGF 是 g(x) ,则 \( g(x) = \sum\limits_{i=0}^{\infty} \frac{i^{i-2}}{i!} x^i \)

令 n 个点的森林的 EGF 是 f(x) ,则 \( f(x) = \sum\limits_{i=0}^{\infty} \frac{g(x)^i}{i!} = e^{g(x)} \)

这道题里,每个团调用 f(x) 的对应项系数,n 条边就给答案乘上 2n

但要减去所有团、团之间的边构成一个环的情况。所以考虑 n 个点、1号点与 n 号点在同一棵树里的森林个数的 EGF h(x) 。

有这样的递推式: \( h[n]=\sum\limits_{i=1}^{n-1} g[n-i]*f[i]*\binom{n-2}{i-1} \) ,就是考虑与 1 号点在同一棵树里有 (n-i) 个点。

即 \( \frac{h[n]}{(n-2)!} = \sum\limits_{i=1}^{n-1} \frac{g[n-i]}{(n-i-1)!} * \frac{f[i]}{(i-1)!} \)

到这里,自己本来想的是后面的就是 \( x*f'(x) \) 和 \( x*g'(x) \) ,然后卷积。不过看看题解,发现前面是 h(x) 的二阶导,后面是 f(x) 和 g(x) 的一阶导。

那么 \( h(x) = \int \int f'(x)*g'(x) dx dx \)

注意数组长度是 219 而不是 218 ,因为倍增的 %t 的 t 可能是 218 ,此时的 len 应该是 219

注意预处理逆元要到 219 ,而不是和 jc[ ] ,jcn[ ] 一样只是 105

注意积分的时候要倒序遍历,以防 a[ ] 和 b[ ] 是同一个数组。

注意 get_exp( ) 的时候,本层的 len 要在 get_inv( ) 之后再赋值。并注意 \( 1-ln(f_0(x))+a(x) \) 的那个 1 是常数项,不是每项都有一个+1。

注意 \( i^{i-2} \) 里的 i 不能是 1 。

注意最后算 h(x) 的时候做积分,随便找了两个数组存积分结果,在乘起来之前要先把无关的项清空!!!

注意最后乘上 \( i! \) 才是真正的系数。

  1. #include<cstdio>
  2. #include<cstring>
  3. #include<algorithm>
  4. #define ll long long
  5. using namespace std;
  6. int rdn()
  7. {
  8. int ret=;bool fx=;char ch=getchar();
  9. while(ch>''||ch<''){if(ch=='-')fx=;ch=getchar();}
  10. while(ch>=''&&ch<='')ret=ret*+ch-'',ch=getchar();
  11. return fx?ret:-ret;
  12. }
  13. const int N=(<<)+,mod=;//1<<19 not 18 for t=2^18
  14. int upt(int x){while(x>=mod)x-=mod;while(x<)x+=mod;return x;}
  15. int pw(int x,int k)
  16. {int ret=;while(k){if(k&)ret=(ll)ret*x%mod;x=(ll)x*x%mod;k>>=;}return ret;}
  17.  
  18. int n,ct[N],f[N],g[N],h[N],jc[N],jcn[N],bin[N];
  19. int la[N],ia[N],tp[N],A[N],len,r[N],inv[N],wn[N],wn2[N];
  20. void ntt_pre(int len)
  21. {
  22. for(int R=;R<=len;R++)
  23. {
  24. wn[R]=pw(,(mod-)/R);
  25. wn2[R]=pw(,(mod-)-(mod-)/R);
  26. }
  27. inv[]=;
  28. for(int i=;i<=len;i++)/////here not in init()
  29. inv[i]=(ll)upt(-mod/i)*inv[mod%i]%mod;
  30. }
  31. void ntt_len()
  32. {
  33. for(int i=,j=len>>;i<len;i++)
  34. r[i]=(r[i>>]>>)+((i&)?j:);
  35. }
  36. void ntt(int *a,bool fx)
  37. {
  38. for(int i=;i<len;i++)
  39. if(i<r[i])swap(a[i],a[r[i]]);
  40. for(int R=;R<=len;R<<=)
  41. {
  42. int Wn=fx?wn2[R]:wn[R];
  43. for(int i=,m=R>>;i<len;i+=R)
  44. for(int j=,w=;j<m;j++,w=(ll)w*Wn%mod)
  45. {
  46. int x=a[i+j],y=(ll)w*a[i+m+j]%mod;
  47. a[i+j]=upt(x+y); a[i+m+j]=upt(x-y);
  48. }
  49. }
  50. if(!fx)return; int iv=inv[len];
  51. for(int i=;i<len;i++)a[i]=(ll)a[i]*iv%mod;
  52. }
  53. void get_dao(int n,int *a,int *b)
  54. {
  55. for(int i=;i<n;i++)b[i]=(ll)(i+)*a[i+]%mod;
  56. b[n]=;
  57. }
  58. void get_jf(int n,int *a,int *b)
  59. {
  60. for(int i=n;i;i--)b[i]=(ll)inv[i]*a[i-]%mod;//
  61. b[]=;
  62. }
  63. void get_inv(int n,int *a,int *b)
  64. {
  65. b[]=pw(a[],mod-);
  66. for(int t=,yt=,i,j;yt<n;yt=t,t=len)
  67. {
  68. len=t<<; ntt_len();
  69. for(i=;i<t;i++)tp[i]=a[i];
  70. for(;i<len;i++)tp[i]=; for(i=yt;i<len;i++)b[i]=;
  71. //b[i]=0 here for other get_inv pollute b[]//<len or t?
  72. ntt(tp,); ntt(b,);
  73. for(i=;i<len;i++)b[i]=upt((ll)b[i]*(-(ll)b[i]*tp[i]%mod)%mod);
  74. ntt(b,);
  75. }
  76. for(int i=n;i<len;i++)b[i]=;
  77. }
  78. void get_ln(int n,int *a,int *b)
  79. {
  80. for(int i=;i<n;i++)ia[i]=;
  81. get_dao(n,a,b); get_inv(n,a,ia);
  82. len=n<<; ntt_len();//len=n<<1 is ok
  83. ntt(b,); ntt(ia,);
  84. for(int i=;i<len;i++)b[i]=(ll)b[i]*ia[i]%mod;
  85. ntt(b,); for(int i=n;i<len;i++)b[i]=;
  86. get_jf(n-,b,b);
  87. }
  88. void get_exp(int n,int *a,int *b)
  89. {
  90. b[]=;
  91. for(int t=,yt=,i,j;yt<n;yt=t,t=len)
  92. {
  93. for(i=yt;i<t;i++)b[i]=; get_ln(t,b,la);//b[i]=0 before
  94. for(i=;i<t;i++)la[i]=upt(-la[i]+a[i]);
  95. la[]=upt(la[]+);/////not la[i]=1-la[i]+a[i]!!!
  96. len=t<<; ntt_len();//////after get_ln!!!!!
  97. ntt(la,); ntt(b,);
  98. for(i=;i<len;i++)b[i]=(ll)la[i]*b[i]%mod;
  99. ntt(b,);
  100. }
  101. for(int i=n;i<len;i++)b[i]=;
  102. }
  103. void init()
  104. {
  105. n=1e5; for(len=;len<=n;len<<=);//len=mx_t
  106. ntt_pre(len<<);
  107. jc[]=;for(int i=;i<=n;i++)jc[i]=(ll)jc[i-]*i%mod;
  108. jcn[n]=pw(jc[n],mod-);
  109. for(int i=n-;i>=;i--)jcn[i]=(ll)jcn[i+]*(i+)%mod;
  110. bin[]=;for(int i=;i<=n;i++)bin[i]=upt(bin[i-]<<);
  111.  
  112. g[]=;
  113. for(int i=;i<=n;i++)//i=2 not i=1!!
  114. g[i]=(ll)pw(i,i-)*jcn[i]%mod;
  115. get_exp(n+,g,f);
  116. get_dao(n,g,ia); get_dao(n,f,la);
  117. for(len=;len<n<<;len<<=); ntt_len();
  118. for(int i=n;i<len;i++)ia[i]=la[i]=;//////!!!!!
  119. ntt(ia,); ntt(la,);
  120. for(int i=;i<len;i++)ia[i]=(ll)ia[i]*la[i]%mod;
  121. ntt(ia,);
  122. get_jf(n,ia,h); get_jf(n,h,h);
  123. for(int i=;i<=n;i++)///
  124. {
  125. f[i]=(ll)f[i]*jc[i]%mod;
  126. g[i]=(ll)g[i]*jc[i]%mod;
  127. h[i]=(ll)h[i]*jc[i]%mod;
  128. }
  129. }
  130. int main()
  131. {
  132. int T=rdn(); init();
  133. while(T--)
  134. {
  135. n=rdn();
  136. for(int i=;i<=n;i++)ct[i]=rdn();
  137. int m1=bin[n],m2=;
  138. for(int i=;i<=n;i++) m1=(ll)m1*f[ct[i]]%mod;
  139. for(int i=;i<=n;i++) m2=(ll)m2*upt(f[ct[i]]-h[ct[i]])%mod;
  140. printf("%d\n",upt(m1-m2));
  141. }
  142. return ;
  143. }

hdu 5279 YJC plays Minecraft——生成函数的更多相关文章

  1. HDU 5279 YJC plays Minecraft(NTT+分治)

    题意 有 \(n\) 个岛屿,第 \(i\) 个岛屿上有一张 \(a_i\) 的完全图.其中第 \(i\) 张完全图的 \(a_i\) 号节点和 \(i+1\) 号岛屿的 \(1\) 号节点有边相连( ...

  2. HDU 5279 YJC plays Minecraft (分治NTT优化DP)

    题目传送门 题目大意:有$n$个小岛,每个小岛上有$a_{i}$个城市,同一个小岛上的城市互相连接形成一个完全图,第$i$个小岛的第$a_{i}$个城市和第$i+1$个小岛的第$1$个城市连接,特别地 ...

  3. 题解 HDU 5279 YJC plays Minecraft

    题目传送门 题目大意 给出\(n\)以及\(a_{1,2,...,n}\),表示有\(n\)个完全图,第\(i\)个完全图大小为\(a_i\),这些完全图之间第\(i\)个完全图的点\(a_i\)与\ ...

  4. hdu5279 YJC plays Minecraft 【分治NTT】

    题目链接 hdu5279 题解 给出若干个完全图,然后完全图之间首尾相连并成环,要求删边使得两点之间路径数不超过\(1\),求方案数 容易想到各个完全图是独立的,每个完全图要删成一个森林,其实就是询问 ...

  5. hdu5279 YJC plays Minecraft

    题目描述 题解: 岛屿之间的边砍/不砍情况有$2^n$种, 但是需要剪掉所有的岛上都首尾相连的情况. $dp$一下对于完全图没有限制($f$)/有限制($g$)的情况数. 方程:$$f[i]=\sum ...

  6. hdu 5277 YJC counts stars

    hdu 5277 YJC counts stars 题意: 给出一个平面图,n个点,m条边,直线边与直线边之间不相交,求最大团的数目. 限制: 1 <= n <= 1000 思路: 因为平 ...

  7. hdu 5277 YJC counts stars 暴力

    YJC counts stars Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php? ...

  8. hdu 5276 YJC tricks time 数学

    YJC tricks time Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?p ...

  9. HDU - 5276 YJC tricks time

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5276   Sample Input 99000 0   Sample Output 00:01:30 ...

随机推荐

  1. Oracle数据库之触发器(二)

    DML触发器是指在进行insert.update或delete操作时触发的程序体.如果你想在用户对数据进行操作时,记录或限制其操作,就可以用DML触发器.举例来说,我想统计我的网站用户的注册.注销或者 ...

  2. flask 实现简易图书管理

    """ 1.配置数据库 a.导入 SQLalchemy库 b.创建db对象,并配置参数 c.创建数据库 2.添加书和作者的模型 a.模型集成db.Model b.__ta ...

  3. C++中若类中没有默认构造函数,如何使用对象数组

    前言: 如果定义一个类,有其默认的构造函数,则使用new动态实例化一个对象数组,不是件难事,如下代码: #include <memory> #include <iostream> ...

  4. Hive date_add 和 date_diff 函数

    date_add 函数 例子:date_add('day',-1,current_date) date_diff 函数 例子:date_diff('day',cast(a.dt1 as timesta ...

  5. SPRING CLOUD微服务DEMO-下篇

    目录 1 Hystix 1.1 简介 1.2 配置并测试 2. Feign 2.1 简介 2.2 使用Feign 2.3 负载均衡 2.4 Hystrix支持 2.5.请求压缩 3. Zuul网关 3 ...

  6. python让人头大的装饰器...decorator带参不带参用法和原理.,..

    0. 概念什么叫装饰器,其实也可以叫做包装器.即对于一个既有的函数func(args),在调用它之前和之后,我们希望都做一些事情,把这个函数包装起来. python中的装饰器分为两类:函数装饰器和类装 ...

  7. 【Unity3D NGUI】----UI尺寸和位置的调整

    1 尺寸与位置 通过UIWidget类获取,该类是所有UI元素的基类 在unity中创建一个sprite,如下图所示 这里面这个sprite的大小受几个属性的影响,首先是属性面板里的Size,对应的U ...

  8. 字符串模式匹配算法系列(一):BF算法

    算法背景: BF(Brute Force)算法,是一种在字符串匹配的算法中,比较符合人类自然思维方式的方法,即对源字符串和目标字符串逐个字符地进行比较,直到在源字符串中找到完全与目标字符串匹配的子字符 ...

  9. 【python】 编码转换

    #转码 def utf2gbk(string): #return string s=string.decode('utf-8','ignore').encode('gb18030','ignore') ...

  10. vue 引入阿里图标

    1.去阿里图标矢量图标库将想要的图标添加入库 2.再去库中将图标添加到项目. 3.再到我的项目中,选择,我这里采用的是将图标代码包下载到本地再引入到vue项目中. 4.在vue项目的assets文件夹 ...