LOJ#3102. 「JSOI2019」神经网络

首先我们容易发现就是把树拆成若干条链,然后要求这些链排在一个环上,同一棵树的链不相邻

把树拆成链可以用一个简单(但是需要复杂的分类讨论)的树背包实现

\(dp[u][j][0/1/2]\)表示第\(u\)个点已经选了\(j\)条链,0是两个不同子树的链拼到一起,1是只有1个点,2是有一条至少有两个点的链

通过这个我们可以求一个\(f[k]\)表示把这棵树分成\(k\)条链有几种情况

环排列可以通过全排列除以排列长度得到

我们设把\(k\)条链分成\(h\)个小块,这样我们至少有了\(k - h\)对点同一棵树且相邻,容斥系数乘上\((-1)^{k - h}\),对于全排列来说,我们还需要除以\(h!\)

所以列出一个这样的EGF

\(f[k]k!\binom{k - 1}{h - 1} \frac{x^{h}}{h!}\)

就可以卷积了

然后对于答案的\(x^{h}\)乘上\((h - 1)!\)因为是环排

就可以得到答案

  1. #include <bits/stdc++.h>
  2. #define fi first
  3. #define se second
  4. #define pii pair<int,int>
  5. #define mp make_pair
  6. #define pb push_back
  7. #define space putchar(' ')
  8. #define enter putchar('\n')
  9. #define eps 1e-10
  10. #define ba 47
  11. #define MAXN 5005
  12. //#define ivorysi
  13. using namespace std;
  14. typedef long long int64;
  15. typedef unsigned int u32;
  16. typedef double db;
  17. template<class T>
  18. void read(T &res) {
  19. res = 0;T f = 1;char c = getchar();
  20. while(c < '0' || c > '9') {
  21. if(c == '-') f = -1;
  22. c = getchar();
  23. }
  24. while(c >= '0' && c <= '9') {
  25. res = res * 10 +c - '0';
  26. c = getchar();
  27. }
  28. res *= f;
  29. }
  30. template<class T>
  31. void out(T x) {
  32. if(x < 0) {x = -x;putchar('-');}
  33. if(x >= 10) {
  34. out(x / 10);
  35. }
  36. putchar('0' + x % 10);
  37. }
  38. const int MOD = 998244353,MAXL = (1 << 15);
  39. int W[MAXL + 5];
  40. int fac[100005],invfac[100005];
  41. int inc(int a,int b) {
  42. return a + b >= MOD ? a + b - MOD : a + b;
  43. }
  44. int mul(int a,int b) {
  45. return 1LL * a * b % MOD;
  46. }
  47. void update(int &x,int y) {
  48. x = inc(x,y);
  49. }
  50. int fpow(int x,int c) {
  51. int res = 1,t = x;
  52. while(c) {
  53. if(c & 1) res = mul(res,t);
  54. t = mul(t,t);
  55. c >>= 1;
  56. }
  57. return res;
  58. }
  59. int C(int n,int m) {
  60. if(n < m) return 0;
  61. else return mul(fac[n],mul(invfac[m],invfac[n - m]));
  62. }
  63. void NTT(vector<int> &f,int l,int on) {
  64. f.resize(l);
  65. for(int i = 1,j = l >> 1 ; i < l - 1 ; ++i) {
  66. if(i < j) swap(f[i],f[j]);
  67. int k = l >> 1;
  68. while(j >= k) {
  69. j -= k;
  70. k >>= 1;
  71. }
  72. j += k;
  73. }
  74. for(int h = 2 ; h <= l ; h <<= 1) {
  75. int wn = W[(MAXL + on * MAXL / h) % MAXL];
  76. for(int k = 0 ; k < l ; k += h) {
  77. int w = 1;
  78. for(int j = k ; j < k + h / 2 ; ++j) {
  79. int u = f[j],t = mul(w,f[j + h / 2]);
  80. f[j] = inc(u,t);
  81. f[j + h / 2] = inc(u,MOD - t);
  82. w = mul(w,wn);
  83. }
  84. }
  85. }
  86. if(on == -1) {
  87. int invL = fpow(l,MOD - 2);
  88. for(int i = 0 ; i < l ; ++i) f[i] = mul(f[i],invL);
  89. }
  90. }
  91. vector<int> operator * (vector<int> a,vector<int> b) {
  92. vector<int> c;
  93. int l = 1;
  94. while(l <= a.size() - 1 + b.size() - 1) l <<= 1;
  95. NTT(a,l,1);NTT(b,l,1);
  96. c.resize(l);
  97. for(int i = 0 ; i < l ; ++i) c[i] = mul(a[i],b[i]);
  98. NTT(c,l,-1);
  99. int s = c.size() - 1;
  100. while(s > 0) {
  101. if(c[s] == 0) {c.pop_back();--s;}
  102. else break;
  103. }
  104. return c;
  105. }
  106. void Init() {
  107. W[0] = 1;W[1] = fpow(3,(MOD - 1) / MAXL);
  108. for(int i = 2 ; i < MAXL ; ++i) W[i] = mul(W[i - 1],W[1]);
  109. fac[0] = 1;
  110. for(int i = 1 ; i <= 100000 ; ++i) fac[i] = mul(fac[i - 1],i);
  111. invfac[100000] = fpow(fac[100000],MOD - 2);
  112. for(int i = 99999 ; i >= 0 ; --i) invfac[i] = mul(invfac[i + 1],i + 1);
  113. }
  114. int M,K;
  115. struct node {
  116. int to,next;
  117. }E[100005];
  118. int head[5005],sumE,siz[5005];
  119. int dp[5005][5005][3],g[5005][3],f[5005],all;
  120. vector<int> z,ans;
  121. void add(int u,int v) {
  122. E[++sumE].to = v;
  123. E[sumE].next = head[u];
  124. head[u] = sumE;
  125. }
  126. void dfs(int u,int fa) {
  127. dp[u][0][1] = 1;
  128. siz[u] = 1;
  129. for(int i = head[u] ; i ; i = E[i].next) {
  130. int v = E[i].to;
  131. if(v != fa) {
  132. dfs(v,u);
  133. for(int j = 0 ; j <= siz[u] + siz[v] ; ++j) memset(g[j],0,sizeof(g[j]));
  134. for(int j = 0 ; j <= siz[u] ; ++j) {
  135. for(int h = 0 ; h <= siz[v] ; ++h) {
  136. int t0 = inc(dp[v][h][1],mul(dp[v][h][2],2));
  137. int t1 = inc(dp[v][h][1],dp[v][h][2]);
  138. update(g[j + h][0],mul(dp[u][j][0],dp[v][h][0]));
  139. update(g[j + h + 1][0],mul(dp[u][j][0],t0));;
  140. update(g[j + h][1],mul(dp[u][j][1],dp[v][h][0]));
  141. update(g[j + h + 1][1],mul(dp[u][j][1],t0));
  142. update(g[j + h][2],mul(dp[u][j][1],t1));
  143. update(g[j + h][2],mul(dp[u][j][2],dp[v][h][0]));
  144. update(g[j + h + 1][2],mul(dp[u][j][2],t0));
  145. update(g[j + h + 1][0],mul(dp[u][j][2],mul(2,t1)));
  146. }
  147. }
  148. siz[u] += siz[v];
  149. for(int j = 0 ; j <= siz[u] ; ++j) {
  150. for(int h = 0 ; h < 3 ; ++h) {
  151. dp[u][j][h] = g[j][h];
  152. }
  153. }
  154. }
  155. }
  156. if(!fa) {
  157. memset(f,0,sizeof(f));
  158. for(int j = 0 ; j <= siz[1] ; ++j) {
  159. update(f[j],dp[1][j][0]);
  160. update(f[j + 1],dp[1][j][1]);
  161. update(f[j + 1],mul(2,dp[1][j][2]));
  162. }
  163. }
  164. }
  165. void Solve() {
  166. read(M);
  167. ans.pb(1);
  168. for(int i = 1 ; i <= M ; ++i) {
  169. sumE = 0;
  170. memset(head,0,sizeof(head));
  171. memset(siz,0,sizeof(siz));
  172. for(int j = 0 ; j <= K ; ++j) {
  173. for(int h = 0 ; h <= K ; ++h) {
  174. memset(dp[j][h],0,sizeof(dp[j][h]));
  175. }
  176. }
  177. read(K);
  178. all += K;
  179. int a,b;
  180. for(int j = 1 ; j < K ; ++j) {
  181. read(a);read(b);
  182. add(a,b);add(b,a);
  183. }
  184. dfs(1,0);
  185. z.clear();
  186. z.resize(K + 1);
  187. for(int j = K ; j >= 1 ; --j) {
  188. int a = mul(f[j],fac[j]);
  189. for(int h = j ; h >= 1 ; --h) {
  190. int t = mul(a,C(j - 1,h - 1));
  191. if((j - h) & 1) t = MOD - t;
  192. update(z[h],t);
  193. }
  194. }
  195. for(int j = 0 ; j <= K ; ++j) z[j] = mul(z[j],invfac[j]);
  196. ans = ans * z;
  197. }
  198. int res = 0;
  199. for(int i = 1 ; i <= all ; ++i) {
  200. update(res,mul(ans[i],fac[i - 1]));
  201. }
  202. out(res);enter;
  203. }
  204. int main(){
  205. #ifdef ivorysi
  206. freopen("f1.in","r",stdin);
  207. #endif
  208. Init();
  209. Solve();
  210. }

【LOJ】#3102. 「JSOI2019」神经网络的更多相关文章

  1. Loj #3102. 「JSOI2019」神经网络

    Loj #3102. 「JSOI2019」神经网络 题目背景 火星探险队发现,火星人的思维方式与人类非常不同,是因为他们拥有与人类很不一样的神经网络结构.为了更好地理解火星人的行为模式,JYY 对小镇 ...

  2. LOJ #3103. 「JSOI2019」节日庆典

    题意 给定字符串 \(S\) ,对于 \(S\) 的每个前缀 \(T\) 求 \(T\) 所有循环同构串的字典序最小的串,输出其起始下标.(如有多个输出最靠前的) \(|S| \le 3 \times ...

  3. LOJ3102. 「JSOI2019」神经网络 [DP,容斥,生成函数]

    传送门 思路 大部分是感性理解,不保证完全正确. 不能算是神仙题,但我还是不会qwq 这题显然就是求:把每一棵树分成若干条链,然后把链拼成一个环,使得相邻的链不来自同一棵树,的方案数.(我才不告诉你们 ...

  4. 【LOJ】#3103. 「JSOI2019」节日庆典

    LOJ#3103. 「JSOI2019」节日庆典 能当最小位置的值一定是一个最小后缀,而有用的最小后缀不超过\(\log n\)个 为什么不超过\(\log n\)个,看了一下zsy的博客.. 假如\ ...

  5. 【LOJ】#3101. 「JSOI2019」精准预测

    LOJ#3101. 「JSOI2019」精准预测 设0是生,1是死,按2-sat连边那么第一种情况是\((t,x,1) \rightarrow (t + 1,y,1)\),\((t + 1,y, 0) ...

  6. Loj #2192. 「SHOI2014」概率充电器

    Loj #2192. 「SHOI2014」概率充电器 题目描述 著名的电子产品品牌 SHOI 刚刚发布了引领世界潮流的下一代电子产品--概率充电器: 「采用全新纳米级加工技术,实现元件与导线能否通电完 ...

  7. Loj #3096. 「SNOI2019」数论

    Loj #3096. 「SNOI2019」数论 题目描述 给出正整数 \(P, Q, T\),大小为 \(n\) 的整数集 \(A\) 和大小为 \(m\) 的整数集 \(B\),请你求出: \[ \ ...

  8. Loj #3093. 「BJOI2019」光线

    Loj #3093. 「BJOI2019」光线 题目描述 当一束光打到一层玻璃上时,有一定比例的光会穿过这层玻璃,一定比例的光会被反射回去,剩下的光被玻璃吸收. 设对于任意 \(x\),有 \(x\t ...

  9. Loj #3089. 「BJOI2019」奥术神杖

    Loj #3089. 「BJOI2019」奥术神杖 题目描述 Bezorath 大陆抵抗地灾军团入侵的战争进入了僵持的阶段,世世代代生活在 Bezorath 这片大陆的精灵们开始寻找远古时代诸神遗留的 ...

随机推荐

  1. Java进阶知识22 Spring execution 切入点表达式

    1.概述   切入点(execution ):可以对指定的方法进行拦截,从而给指定的类生成代理对象.(拦截谁,就是在谁那里切入指定的程序/方法) 格式: execution(modifiers-pat ...

  2. 2018-2019 ACM-ICPC, China Multi-Provincial Collegiate Programming Contest

    目录 Contest Info Solutions A. Maximum Element In A Stack B. Rolling The Polygon C. Caesar Cipherq D. ...

  3. Simple Problem with Integers(POJ 3486)

                                                                  A Simple Problem with Integers Time Li ...

  4. shell 获取指定ip的丢包率

    shell 获取指定ip的丢包率 丢包率大于10%就重新网络 使用sed 替换字符串 [[ $(ping -c 10 -W 1 baidu.com | awk '$6 ~ /%/{print $6}' ...

  5. SpringMVC配置 事务管理

    1.确保持久层配置完毕 2.pom.xml里追加spring-tx 3.application-context.xml追加 <bean id="transactionManager&q ...

  6. vim 操作命令

    #显示行号,设定之后,会在每一行的前缀显示该行的行号:set nu #取消行号显示:set nonu #将编辑的数据写入硬盘档案中(常用):w #若文件属性为『只读』时,强制写入该档案.不过,到底能不 ...

  7. Linux环境下levelDB源码编译与安装

    1.下载源码并编译 git clone https://github.com/google/leveldb.git cd leveldb //编译源码的时候需要安装cmake,并且版本需要大于3.9, ...

  8. Atcoder ABC 139E

    Atcoder ABC 139E 题意: n支球队大循环赛,每支队伍一天只能打一场,求最少几天能打完. 解法: 考虑抽象图论模型,既然一天只能打一场,那么就把每一支球队和它需要交手的球队连边. 求出拓 ...

  9. Hadoop 3.2.1 win10 64位系统 vs2015 编译

    Hadoop 3.2.1 win10 64位系统 vs2015 编译 1        环境配置 1.1   JDK下载安装 1.1.1         下载 JDK 1.8    (jdk1.8.0 ...

  10. 三、Navicat将远程MySql数据库数据导入本地

    1.安装本地的MySql.记住用户名和密码,这里以root,root为例. 2.打开Navicat,新建连接(连接),输入连接名,用户名,密码.确定,连接测试.这里连接名为luzhanshi.这样本地 ...