当时看到这道题的时候我的脑子可能是这样的:

My left brain has nothing right, and my right brain has nothing left.

总之,看到"没有鸡你太美"这一类就直接想容斥,转化为”选出$i$个鸡你太美“

看到排列问题,直接想指数型生成函数。

设$m=\min(\frac{n}{4},a,b,c,d)$

我们使用万年不变的捆绑法,将鸡你太美当做整体考虑,即在$n-3i$个元素中选$i$个作为鸡你太美,再对其他四种进行全排列。

$$ans=\sum_{i=0}^m(-1)^i(n-4i)!\binom{n-3i}{i}\sum_{i_1\leq a-i}\sum_{i_2\leq b-i}\sum_{i_3\leq c-i}\sum_{i_4\leq d-i}\frac{1}{\prod i_j!}[\sum i_j=n-4i]$$

$$\sum_{i=0}^m(-1)^i\frac{(n-3i)!}{i!}\sum_{i_1\leq a-i}\sum_{i_2\leq b-i}\sum_{i_3\leq c-i}\sum_{i_4\leq d-i}\frac{1}{\prod i_j!}[\sum i_j=n-4i]$$

后面那一长串可以用NTT优化计算。

时间复杂度$O(n^2\log n)$,听说有直接dp的$O(n^2)$做法,但这个生成函数的做法应该是无脑多了。

 #include<bits/stdc++.h>
#define Rint register int
using namespace std;
typedef long long LL;
const int N = << , mod = , g = , gi = ;
inline int kasumi(int a, int b){
int res = ;
while(b){
if(b & ) res = (LL) res * a % mod;
a = (LL) a * a % mod;
b >>= ;
}
return res;
}
int fac[N], inv[N];
inline void init(int n){
fac[] = ;
for(Rint i = ;i <= n;i ++) fac[i] = (LL) i * fac[i - ] % mod;
inv[n] = kasumi(fac[n], mod - );
for(Rint i = n;i;i --) inv[i - ] = (LL) inv[i] * i % mod;
}
int rev[N];
inline int calrev(int n){
int limit = , L = -;
while(limit <= n){limit <<= ; L ++;}
for(Rint i = ;i < limit;i ++) rev[i] = (rev[i >> ] >> ) | ((i & ) << L);
return limit;
}
inline void NTT(int *A, int limit, int type){
for(Rint i = ;i < limit;i ++) if(i < rev[i]) swap(A[i], A[rev[i]]);
for(Rint mid = ;mid < limit;mid <<= ){
int Wn = kasumi(type == ? g : gi, (mod - ) / (mid << ));
for(Rint j = ;j < limit;j += mid << ){
int w = ;
for(Rint k = ;k < mid;k ++, w = (LL) w * Wn % mod){
int x = A[j + k], y = (LL) w * A[j + k + mid] % mod;
A[j + k] = (x + y) % mod;
A[j + k + mid] = (x - y + mod) % mod;
}
}
}
if(type == -){
int inv = kasumi(limit, mod - );
for(Rint i = ;i < limit;i ++)
A[i] = (LL) A[i] * inv % mod;
}
}
int n, a, b, c, d, m, ans, A[N], B[N], C[N], D[N];
int main(){
scanf("%d%d%d%d%d", &n, &a, &b, &c, &d);
init(a + b + c + d);
m = min(n >> , min(min(a, b), min(c, d)));
for(Rint i = ;i <= m;i ++){
int limit = calrev(a + b + c + d - (i << ));
for(Rint j = ;j < limit;j ++){
A[j] = inv[j] * (j <= a - i);
B[j] = inv[j] * (j <= b - i);
C[j] = inv[j] * (j <= c - i);
D[j] = inv[j] * (j <= d - i);
}
NTT(A, limit, ); NTT(B, limit, ); NTT(C, limit, ); NTT(D, limit, );
for(Rint j = ;j < limit;j ++) A[j] = (LL) A[j] * B[j] % mod * C[j] % mod * D[j] % mod;
NTT(A, limit, -);
int tmp = (LL) A[n - (i << )] * fac[n - * i] % mod * inv[i] % mod;
if(i & ) ans = (ans - tmp + mod) % mod;
else ans = (ans + tmp) % mod;
}
printf("%d", ans);
}

Luogu5339

Luogu5339 [TJOI2019]唱、跳、rap和篮球 【生成函数,NTT】的更多相关文章

  1. [bzoj5510]唱跳rap和篮球

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

  2. [luogu5339] [TJOI2019]唱、跳、rap和篮球(容斥原理+组合数学)(不用NTT)

    [luogu5339] [TJOI2019]唱.跳.rap和篮球(容斥原理+组合数学)(不用NTT) 题面 略 分析 首先考虑容斥,求出有i堆人讨论的方案. 可以用捆绑法,把每堆4个人捆绑成一组,其他 ...

  3. 将Android手机无线连接到Ubuntu实现唱跳Rap

    您想要将Android设备连接到Ubuntu以传输文件.查看Android通知.以及从Ubuntu桌面发送短信 – 你会怎么做?将文件从手机传输到PC时不要打电话给自己:使用GSConnect就可以. ...

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

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

  5. [TJOI2019]唱、跳、rap和篮球——NTT+生成函数+容斥

    题目链接: [TJOI2019]唱.跳.rap和篮球 直接求不好求,我们考虑容斥,求出至少有$i$个聚集区间的方案数$ans_{i}$,那么最终答案就是$\sum\limits_{i=0}^{n}(- ...

  6. 「TJOI2019」唱、跳、rap 和篮球 题解

    题意就不用讲了吧-- 鸡你太美!!! 题意: 有 \(4\) 种喜好不同的人,分别最爱唱.跳. \(rap\).篮球,他们个数分别为 \(A,B,C,D\) ,现从他们中挑选出 \(n\) 个人并进行 ...

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

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

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

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

  9. [LOJ3106][TJOI2019]唱、跳、rap和篮球:DP+生成函数+NTT+容斥原理

    分析 令\(f(i)\)表示共\(i\)组同学讨论cxk的位置的方案数(不考虑其他位置上的人的爱好),这个数组可以很容易地通过依次考虑每个位置是否是四个人中最后一个人的位置来递推求解,时间复杂度\(O ...

随机推荐

  1. 待续:s5p6818移植 uboot 2014.07 移植

    前言: 之前半年一直在嵌入式Linux移植中挣扎,不知道该从哪个方面开始入手,也失败了很多次,苦思了很久最终决定先从uboot开始. uboot版本的不同会导致添加板子的时候的配置方法会不一样.由于手 ...

  2. 三种TCP协议聊天室实现

    一 概述 使用Java的IO实现聊天室 使用Java的NIO实现聊天室 使用Netty实现聊天室 二 IO聊天室 1 服务器 public class IOServer { public static ...

  3. sftp配置多个用户权限的问题

    groupadd group1 chmod 0755 /test/useradd -g group1 -d /test/backend/ -M test_backendusermod -s /sbin ...

  4. 两个重叠的div做前后翻转

    当需要做一个翻转卡片式的div时候,需要两个div的大小等大例如: 画出两个等大的div后,将他们重叠 图中的两个div做了重叠,做重叠时候用的属性是 position: absolute; 并且需要 ...

  5. 现有项目springmvc 小结

    1. 接口接收json数据 @RequestBody JSONObject param 2.返回json数据封装 DataPacket.jsonResult

  6. K2 BPM_北汽新能源业务流程管理信息系统建设思考_全球领先的工作流引擎

    本文由CIO发展中心根据北汽新能源流程与IT总监刘伟霞在“亦庄CIO数字化转型探索——CIO发展中心亦庄分舵2019夏季论坛”活动中演讲整理. 在“亦庄CIO数字化转型探索——CIO发展中心亦庄分舵2 ...

  7. linux命令安装docker

    安装: 1.Docker要求CentOS系统的内核版本高于 3.10 ,通过 uname -r 命令查看你当前的内核版本是否支持安账docker 2.更新yum包:sudo yum update 3. ...

  8. 字符串转json数组

    import net.sf.json.JSONArray;import net.sf.json.JSONObject; String content = inBankOdd.getContent(). ...

  9. c#排序sql语句查询

    排序存储的效果图: 根据id排序的sql存储过程: DECLARE @type varchar() ' ' Order By charindex(','+ convert(varchar,id) +' ...

  10. 【vue开发】vue指令Vue.directive使用教程

    1.指令的注册 指令跟组件一样需要注册才能使用,同样有两种方式,一种是全局注册: ? 1 2 3 4 5 Vue.directive('dirName',function(){   //定义指令   ...