题目传送门

题目大意

给出\(n\)以及\(a_{1,2,...,n}\),表示有\(n\)个完全图,第\(i\)个完全图大小为\(a_i\),这些完全图之间第\(i\)个完全图的点\(a_i\)与\(i\bmod n+1\)的点\(1\)相连。问有多少种方法可以删掉某些边,使得整个图变成一个森林。

思路

话说因为是英文懒得读题,直接看题解里面的题目大意,结果一直理解不了,后来才发现他意思写错了。。。所以说一个正确的题目大意有多重要(雾

有一个人尽皆知的知识,就是\(n\)个点的树有\(n^{n-2}\)个。下面会用到这个东西。

我们设\(f_i\)表示\(i\)个点的完全图删掉一些边变成森林的方案数。可以得到:

\[f_n=\sum_{i=0}^{n-1}\binom{n-1}{i}f_i(n-i)^{n-i-2}
\]
\[=(n-1)!\sum_{i=0}^{n-1}\frac{f_i}{i!}\frac{(n-i)^{n-i-2}}{(n-i-1)!}
\]

这个式子的意思就是我们可以先固定一个点,然后从\(n-1\)选出\(i\)个点单独成森林,然后剩下的点组成一棵树。

然后我们发现这个式子我们其实可以使用分治\(\text {NTT}\)预处理\(\Theta(n\log^2 n)\)之内求出来。

我们考虑如何统计答案。我们发现其实可以使用容斥原理求到:

\[\text {ans}=2^n\prod_{i=1}^{n} f_{a_i}-\prod_{i=1}^{n} (\sum_{j=2}^{a_i}\binom{a_i-2}{j-2}j^{j-2}f_{a_i-j})
\]

前面一个的意思就是统计所有的答案,完全图之间管它连不连,后面一个就是整个图构成一个大环(这其实并不准确,但是意思到位就行)。既然要构成大环,肯定一个完全图内首尾要相连,就肯定是一棵树(要删边成森林)。

然后我们发现后面那个式子可以\(\text {NTT}\)预处理,于是我们就解决了这个问题。

总时间复杂度为\(\Theta(\max\{a_i\}\log^2 \max\{a_i\}+Tn)\)。

\(\text {Code}\)

  1. #include <bits/stdc++.h>
  2. using namespace std;
  3. #define Int register int
  4. #define mod 998244353
  5. #define ll long long
  6. #define MAXN 600005
  7. int quick_pow (int a,int b,int c){
  8. int res = 1;for (;b;b >>= 1,a = 1ll * a * a % c) if (b & 1) res = 1ll * res * a % c;
  9. return res;
  10. }
  11. int rev[MAXN];
  12. void NTT (int *a,int len,int type){
  13. #define G 3
  14. #define Gi 332748118
  15. int limit = 1,l = 0;
  16. while (limit < len) limit <<= 1,l ++;
  17. for (Int i = 0;i < limit;++ i) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << l - 1);
  18. for (Int i = 0;i < limit;++ i) if (i < rev[i]) swap (a[i],a[rev[i]]);
  19. for (Int i = 1;i < limit;i <<= 1){
  20. int Wn = quick_pow (type == 1 ? G : Gi,(mod - 1) / (i << 1),mod);
  21. for (Int j = 0;j < limit;j += i << 1)
  22. for (Int k = 0,w = 1;k < i;++ k,w = 1ll * w * Wn % mod){
  23. int x = a[j + k],y = 1ll * w * a[i + j + k] % mod;
  24. a[j + k] = (x + y) % mod,a[i + j + k] = (x + mod - y) % mod;
  25. }
  26. }
  27. if (type == 1) return ;
  28. for (Int i = 0,Inv = quick_pow (limit,mod - 2,mod);i < limit;++ i) a[i] = 1ll * a[i] * Inv % mod;
  29. #undef G
  30. #undef Gi
  31. }
  32. void multi (int *a,int *b,int *c,int len1,int len2){
  33. int limit = 1;
  34. while (limit < len1 + len2 - 1) limit <<= 1;
  35. for (Int i = len1;i < limit;++ i) a[i] = 0;
  36. for (Int i = len2;i < limit;++ i) b[i] = 0;
  37. NTT (a,limit,1),NTT (b,limit,1);
  38. for (Int i = 0;i < limit;++ i) c[i] = 1ll * a[i] * b[i] % mod;
  39. NTT (c,limit,-1);
  40. }
  41. int f[MAXN],g[MAXN],A[MAXN],B[MAXN],C[MAXN],fac[MAXN],ifac[MAXN];
  42. void cdq (int l,int r){
  43. if (l == r){
  44. if (l == 0) f[l] = 1;
  45. else f[l] = 1ll * f[l] * fac[l - 1] % mod;
  46. return ;
  47. }
  48. int mid = (l + r) >> 1;cdq (l,mid);
  49. for (Int i = l;i <= mid;++ i) A[i - l] = 1ll * f[i] * ifac[i] % mod;
  50. B[0] = 1;for (Int i = 2;i <= r - l;++ i) B[i - 1] = 1ll * quick_pow (i,i - 2,mod) * ifac[i - 1] % mod;
  51. multi (A,B,C,mid - l + 1,r - l);
  52. for (Int i = mid + 1;i <= r;++ i) f[i] = (f[i] + C[i - l - 1]) % mod;
  53. cdq (mid + 1,r);
  54. }
  55. template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
  56. template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
  57. template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
  58. signed main(){
  59. #define Maxn 1<<17
  60. #define Maxm 100005
  61. fac[0] = 1;for (Int i = 1;i <= Maxn;++ i) fac[i] = 1ll * fac[i - 1] * i % mod;
  62. ifac[Maxn] = quick_pow (fac[Maxn],mod - 2,mod);for (Int i = Maxn;i;-- i) ifac[i - 1] = 1ll * ifac[i] * i % mod;
  63. cdq (0,Maxm);
  64. for (Int i = 2;i <= Maxm;++ i) A[i - 2] = 1ll * quick_pow (i,i - 2,mod) * ifac[i - 2] % mod;
  65. for (Int i = 0;i <= Maxm - 2;++ i) B[i] = 1ll * f[i] * ifac[i] % mod;
  66. multi (A,B,C,Maxm - 1,Maxm - 1);
  67. g[1] = 1;for (Int i = 2;i <= Maxm;++ i) g[i] = 1ll * fac[i - 2] * C[i - 2] % mod;
  68. int T;read (T);
  69. while (T --){
  70. int n;read (n);int ans = quick_pow (2,n,mod),sum = 1;
  71. for (Int i = 1,a;i <= n;++ i) read (a),ans = 1ll * ans * f[a] % mod,sum = 1ll * sum * g[a] % mod;
  72. write ((ans + mod - sum) % mod),putchar ('\n');
  73. }
  74. return 0;
  75. }

题解 HDU 5279 YJC plays Minecraft的更多相关文章

  1. hdu 5279 YJC plays Minecraft——生成函数

    题目:http://acm.hdu.edu.cn/showproblem.php?pid=5279 令 n 个点的树的 EGF 是 g(x) ,则 \( g(x) = \sum\limits_{i=0 ...

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

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

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

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

  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 5279 Reflect phi 欧拉函数

    Reflect Time Limit: 1 Sec Memory Limit: 256 MB 题目连接 http://bestcoder.hdu.edu.cn/contests/contest_chi ...

随机推荐

  1. Linux系统下的软件管理(rpm)、搭建第三方软件库、yum的黑名单

    对wps-office进行模糊匹配照样可以查找出该软件yum clean all ? ? ? ?##清空yum缓存识别新配置 测验安装wps软件: 安装成功即可使用办公软件 1.yum install ...

  2. Typora代码块配色和标题自带序号的实现代码

    Typora代码块配色和标题自带序号的实现代码 先打开主题文件夹 文件>偏好设置>外观>打开主题文件夹 然后编辑base.user.css(如果没有就新建一个)文件 /*标题自动添加 ...

  3. awk 命令-随笔

    awk语法: awk [option] 'pattern{action}' file ... awk [参数] '条件{动作}' 文件 ... 解析: 命令: awk 参数: -F "&qu ...

  4. RabbitMQ详解(一)——

    RabbitMQ详解(一)-- https://www.cnblogs.com/liuwenwu9527/p/11989216.html https://www.cnblogs.com/ideal-2 ...

  5. .net中使用JSON

    在.NET使用JSON作为数据交换格式 ASP.NET中JSON的序列化和反序列化 三种方式: 使用System.Web.Script.Serialization.JavaScriptSerializ ...

  6. 企业级镜像仓库 harbor

    企业级镜像仓库 harbor 前言 a. 本文主要为 Docker的视频教程 笔记. b. 环境为 CentOS 7.0 云服务器 c. 上一篇:跨 Docker 宿主机网络 overlay 类型 h ...

  7. Linux安装Cockpit监控服务

    CentOS/RHEL 8的新特性之一就是自带了一个cockpit的监控服务.通过c/s架构模式运行,客户端输入ip:端口即可访问 这类似于glances监控. 如果你不是使用的centos/rhel ...

  8. Linux系列(14) - grep

    简述 grep是在文件当中匹配符合条件的字符串,作用是查找文件内容 格式 grep [选项] 字符串 文件名 选项 -i:忽略大小写 -v:排除指定字符串 -n:显示行号 例子 grep " ...

  9. oracle 基础SQL语句 版本5.7.29

    一.表与用户介绍 oracle安装完成后默认会有很多用户,大致分为2类用户:一类是必需的帐户,一类是存储各种应用的帐户,默认密码如下: oracle自带的也会有很多默认表存在: 二.创建用户.创建表空 ...

  10. setTimeout 与setInterval的区别

    setTimeout(code,millisec) 方法用于在指定的毫秒数后调用函数或计算表达式 setInterval(code,millisec) 方法可按照指定的周期(以毫秒计)来调用函数或计算 ...