题目链接:

[TJOI2019]唱、跳、rap和篮球

直接求不好求,我们考虑容斥,求出至少有$i$个聚集区间的方案数$ans_{i}$,那么最终答案就是$\sum\limits_{i=0}^{n}(-1)^i\ ans_{i}$

那么现在只需要考虑至少有$i$个聚集区间的方案数,我们枚举这$i$个区间的起始点位置,一共有$C_{n-3i}^{i}$种方案(可以看作是刚开始先将每个区间后三个位置去掉,从剩下$n-3i$个位置中选出$i$个区间起点,然后再在每个起点后面加上三个位置)。

那么剩下的$n-4i$个位置就是随便放这四种学生,假设第$j$种学生放了$a_{j}$个、一共有$num_{j}$个,那么方案数就是$\frac{(n-4i)!}{\prod_{j=1}^{4}a_{j}!}$。

由此可以构造出这四种学生的生成函数,以第一种学生为例:$\sum\limits_{j=0}^{num_{1}-i}\frac{x^j}{j!}$

将四个生成函数分别用$NTT$乘在一起然后取$x^{n-4i}$前的系数乘上$(n-4i)!$即可得到$n-4i$个位置随便放的方案数。

  1. #include<set>
  2. #include<map>
  3. #include<cmath>
  4. #include<stack>
  5. #include<queue>
  6. #include<bitset>
  7. #include<cstdio>
  8. #include<vector>
  9. #include<cstring>
  10. #include<iostream>
  11. #include<algorithm>
  12. using namespace std;
  13. const int mod=998244353;
  14. int f[3000];
  15. int g[3000];
  16. int inv[2000];
  17. int fac[2000];
  18. int mask;
  19. int n,a,b,c,d;
  20. int ans;
  21. int mn,mx;
  22. int quick(int x,int y)
  23. {
  24. int res=1;
  25. while(y)
  26. {
  27. if(y&1)
  28. {
  29. res=1ll*res*x%mod;
  30. }
  31. x=1ll*x*x%mod;
  32. y>>=1;
  33. }
  34. return res;
  35. }
  36. void NTT(int *a,int len,int opt)
  37. {
  38. for(int i=0,k=0;i<len;i++)
  39. {
  40. if(i>k)
  41. {
  42. swap(a[i],a[k]);
  43. }
  44. for(int j=len>>1;(k^=j)<j;j>>=1);
  45. }
  46. for(int i=2;i<=len;i<<=1)
  47. {
  48. int t=i>>1;
  49. int x=quick(3,(mod-1)/i);
  50. if(opt==-1)
  51. {
  52. x=quick(x,mod-2);
  53. }
  54. for(int j=0;j<len;j+=i)
  55. {
  56. int w=1;
  57. for(int k=j;k<j+t;k++)
  58. {
  59. int tmp=1ll*a[k+t]*w%mod;
  60. a[k+t]=(a[k]-tmp+mod)%mod;
  61. a[k]=(a[k]+tmp)%mod;
  62. w=1ll*w*x%mod;
  63. }
  64. }
  65. }
  66. if(opt==-1)
  67. {
  68. int x=quick(len,mod-2);
  69. for(int i=0;i<len;i++)
  70. {
  71. a[i]=1ll*a[i]*x%mod;
  72. }
  73. }
  74. }
  75. int C(int n,int m)
  76. {
  77. return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;
  78. }
  79. int solve(int x)
  80. {
  81. memset(f,0,sizeof(f));
  82. memset(g,0,sizeof(g));
  83. for(int i=0;i<=a-x;i++)
  84. {
  85. f[i]=inv[i];
  86. }
  87. for(int i=0;i<=b-x;i++)
  88. {
  89. g[i]=inv[i];
  90. }
  91. NTT(f,mask,1);
  92. NTT(g,mask,1);
  93. for(int i=0;i<mask;i++)
  94. {
  95. f[i]=1ll*f[i]*g[i]%mod;
  96. }
  97. memset(g,0,sizeof(g));
  98. for(int i=0;i<=c-x;i++)
  99. {
  100. g[i]=inv[i];
  101. }
  102. NTT(g,mask,1);
  103. for(int i=0;i<mask;i++)
  104. {
  105. f[i]=1ll*f[i]*g[i]%mod;
  106. }
  107. memset(g,0,sizeof(g));
  108. for(int i=0;i<=d-x;i++)
  109. {
  110. g[i]=inv[i];
  111. }
  112. NTT(g,mask,1);
  113. for(int i=0;i<mask;i++)
  114. {
  115. f[i]=1ll*f[i]*g[i]%mod;
  116. }
  117. NTT(f,mask,-1);
  118. return 1ll*f[n-4*x]*fac[n-4*x]%mod*C(n-3*x,x)%mod;
  119. }
  120. int main()
  121. {
  122. inv[1]=inv[0]=fac[0]=1;
  123. for(int i=1;i<=1000;i++)
  124. {
  125. fac[i]=1ll*fac[i-1]*i%mod;
  126. }
  127. for(int i=2;i<=1000;i++)
  128. {
  129. inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
  130. }
  131. for(int i=1;i<=1000;i++)
  132. {
  133. inv[i]=1ll*inv[i-1]*inv[i]%mod;
  134. }
  135. mask=1;
  136. scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
  137. mn=min(n/4,min(min(a,b),min(c,d)));
  138. mx=max(max(a,b),max(c,d));
  139. while(mask<=(mx<<2))
  140. {
  141. mask<<=1;
  142. }
  143. for(int i=0;i<=mn;i++)
  144. {
  145. if(i&1)
  146. {
  147. ans=(ans-solve(i)+mod)%mod;
  148. }
  149. else
  150. {
  151. ans=(ans+solve(i))%mod;
  152. }
  153. }
  154. printf("%d",ans);
  155. }

[TJOI2019]唱、跳、rap和篮球——NTT+生成函数+容斥的更多相关文章

  1. [bzoj5510]唱跳rap和篮球

    显然答案可以理解为有(不是仅有)0对情况-1对情况+2对情况-- 考虑这个怎么计算,先计算这t对情况的位置,有c(n-3t,t)种情况(可以理解为将这4个点缩为1个,然后再从中选t个位置),然后相当于 ...

  2. [TJOI2019]唱、跳、rap和篮球_生成函数_容斥原理_ntt

    [TJOI2019]唱.跳.rap和篮球 这么多人过没人写题解啊 那我就随便说说了嗷 这题第一步挺套路的,就是题目要求不能存在balabala的时候考虑正难则反,要求必须存在的方案数然后用总数减,往往 ...

  3. Luogu5339 [TJOI2019]唱、跳、rap和篮球 【生成函数,NTT】

    当时看到这道题的时候我的脑子可能是这样的: My left brain has nothing right, and my right brain has nothing left. 总之,看到&qu ...

  4. [TJOI2019]唱、跳、rap和篮球——容斥原理+生成函数

    先附一组sd图 然后放上原题链接 注意,队伍不同指的是喜好不同,不是人不同 先想到\(DP\),然后你会发现并没有什么优秀的状态设计,然后我们考虑容斥 设\(lim\)表示选的癌坤组数的上限,\(f_ ...

  5. 洛谷 P6295 - 有标号 DAG 计数(生成函数+容斥+NTT)

    洛谷题面传送门 看到图计数的题就条件反射地认为是不可做题并点开了题解--实际上这题以我现在的水平还是有可能能独立解决的( 首先连通这个条件有点棘手,我们尝试把它去掉.考虑这题的套路,我们设 \(f_n ...

  6. HDU 6270 Marriage (2017 CCPC 杭州赛区 G题,生成函数 + 容斥 + 分治NTT)

    题目链接  2017 CCPC Hangzhou Problem G 题意描述很清晰. 考虑每个家庭有且仅有$k$对近亲的方案数: $C(a, k) * C(b, k) * k!$ 那么如果在第$1$ ...

  7. 【loj#6503.】「雅礼集训 2018 Day4」Magic(生成函数+容斥)

    题面 传送门 题解 复杂度比较迷啊-- 以下以\(n\)表示颜色总数,\(m\)表示总的卡牌数 严格\(k\)对比较难算,我们考虑容斥 首先有\(i\)对就代表整个序列被分成了\(m-i\)块互不相同 ...

  8. 洛谷P5206 [WC2019] 数树(生成函数+容斥+矩阵树)

    题面 传送门 前置芝士 矩阵树,基本容斥原理,生成函数,多项式\(\exp\) 题解 我也想哭了--orz rqy,orz shadowice 我们设\(T1,T2\)为两棵树,并定义一个权值函数\( ...

  9. [TJOI2019]唱,跳,rap,篮球(生成函数,组合数学,NTT)

    算是补了个万年大坑了吧. 根据 wwj 的题解(最准确),设一个方案 \(S\)(不一定合法)的鸡你太美组数为 \(w(S)\). 答案就是 \(\sum\limits_{S}[w(S)=0]\). ...

随机推荐

  1. SVM支持向量机实例

    波士顿房价回归分析 1.导入波士顿房价数据集 ############################# svm实例--波士顿房价回归分析 ############################## ...

  2. CentOS 6.5 iptables原理详解以及功能说明

    CentOS 6.5 iptables原理详解以及功能说明 来源 https://blog.51cto.com/tanxw/1389114 前言 iptables其实就是Linux下的一个开源的信息过 ...

  3. hadoop入门-centos7.2安装hadoop2.8

    1. 安装准备 (1)必须安装jdk: 因为hadoop是基于Java实现的,所有必须安装jdk 是JDK不是jre jdk1.7 jdk1.8 (2)系统位数 (3)创建专用用户 useradd h ...

  4. dvaJS Model之间的调用

    const Model: ModelType = { namespace: 'namesps', state: { data: {} }, effects: { *fetch({ payload, c ...

  5. 阿里云服务器(Ubuntu16.04 64位)的使用

    购买阿里云服务器 1.打开阿里云官方网站,账号登录,选择产品中的云服务器 ECS 2.根据自身需求,选择合适的阿里云服务器系统,(1)点击一键购买,(2)选择地域,(3)根据自身需求,选择系统,这里选 ...

  6. SAP Marketing Cloud功能简述(三) 营销活动内容设计和产品推荐

    Grace的前两篇文章: SAP Marketing Cloud功能简述(一) : Contacts和Profiles SAP Marketing Cloud功能简述(二) : Target Grou ...

  7. 安装xshell、xftp

    1.Xshell的软件的下载.安装 xshell是一个终端模拟软件,而且是远程近程都可以. 就是模拟服务器所在的linux,在xshell中可以输入命令, 就像在服务器的linux中输入命令一样.一般 ...

  8. javascript_14-对象

    什么是对象 生活中的对象,一个车.一个手机 对象具有特性和行为 面向对象和基于对象 面向对象:可以创建自定义的类型.很好的支持继承和多态.面向对象的语言有 c++ .Java. C# ... 面向对象 ...

  9. Linux命令——su 、su -、sudo

    前言 大部分Linux发行版的默认账户是普通用户,而更改系统文件或者执行某些命令,需要root身份才能进行,这就需要从当前用户切换到root用户. 切换用户身份有两个命令 su [-] usernam ...

  10. Linux系统Zip压缩和解压缩

    Linux系统可以使用Zip来压缩占用空间较大的文件以便进行文件传输,传输完成后再进行解压缩来获取原文件.Linux安装Zip的命令为 apt-get install zip 安装完成后,使用 zip ...