[TJOI2019]唱、跳、rap和篮球——NTT+生成函数+容斥
题目链接:
直接求不好求,我们考虑容斥,求出至少有$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$个位置随便放的方案数。
#include<set>
#include<map>
#include<cmath>
#include<stack>
#include<queue>
#include<bitset>
#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int mod=998244353;
int f[3000];
int g[3000];
int inv[2000];
int fac[2000];
int mask;
int n,a,b,c,d;
int ans;
int mn,mx;
int quick(int x,int y)
{
int res=1;
while(y)
{
if(y&1)
{
res=1ll*res*x%mod;
}
x=1ll*x*x%mod;
y>>=1;
}
return res;
}
void NTT(int *a,int len,int opt)
{
for(int i=0,k=0;i<len;i++)
{
if(i>k)
{
swap(a[i],a[k]);
}
for(int j=len>>1;(k^=j)<j;j>>=1);
}
for(int i=2;i<=len;i<<=1)
{
int t=i>>1;
int x=quick(3,(mod-1)/i);
if(opt==-1)
{
x=quick(x,mod-2);
}
for(int j=0;j<len;j+=i)
{
int w=1;
for(int k=j;k<j+t;k++)
{
int tmp=1ll*a[k+t]*w%mod;
a[k+t]=(a[k]-tmp+mod)%mod;
a[k]=(a[k]+tmp)%mod;
w=1ll*w*x%mod;
}
}
}
if(opt==-1)
{
int x=quick(len,mod-2);
for(int i=0;i<len;i++)
{
a[i]=1ll*a[i]*x%mod;
}
}
}
int C(int n,int m)
{
return 1ll*fac[n]*inv[m]%mod*inv[n-m]%mod;
}
int solve(int x)
{
memset(f,0,sizeof(f));
memset(g,0,sizeof(g));
for(int i=0;i<=a-x;i++)
{
f[i]=inv[i];
}
for(int i=0;i<=b-x;i++)
{
g[i]=inv[i];
}
NTT(f,mask,1);
NTT(g,mask,1);
for(int i=0;i<mask;i++)
{
f[i]=1ll*f[i]*g[i]%mod;
}
memset(g,0,sizeof(g));
for(int i=0;i<=c-x;i++)
{
g[i]=inv[i];
}
NTT(g,mask,1);
for(int i=0;i<mask;i++)
{
f[i]=1ll*f[i]*g[i]%mod;
}
memset(g,0,sizeof(g));
for(int i=0;i<=d-x;i++)
{
g[i]=inv[i];
}
NTT(g,mask,1);
for(int i=0;i<mask;i++)
{
f[i]=1ll*f[i]*g[i]%mod;
}
NTT(f,mask,-1);
return 1ll*f[n-4*x]*fac[n-4*x]%mod*C(n-3*x,x)%mod;
}
int main()
{
inv[1]=inv[0]=fac[0]=1;
for(int i=1;i<=1000;i++)
{
fac[i]=1ll*fac[i-1]*i%mod;
}
for(int i=2;i<=1000;i++)
{
inv[i]=1ll*(mod-mod/i)*inv[mod%i]%mod;
}
for(int i=1;i<=1000;i++)
{
inv[i]=1ll*inv[i-1]*inv[i]%mod;
}
mask=1;
scanf("%d%d%d%d%d",&n,&a,&b,&c,&d);
mn=min(n/4,min(min(a,b),min(c,d)));
mx=max(max(a,b),max(c,d));
while(mask<=(mx<<2))
{
mask<<=1;
}
for(int i=0;i<=mn;i++)
{
if(i&1)
{
ans=(ans-solve(i)+mod)%mod;
}
else
{
ans=(ans+solve(i))%mod;
}
}
printf("%d",ans);
}
[TJOI2019]唱、跳、rap和篮球——NTT+生成函数+容斥的更多相关文章
- [bzoj5510]唱跳rap和篮球
显然答案可以理解为有(不是仅有)0对情况-1对情况+2对情况-- 考虑这个怎么计算,先计算这t对情况的位置,有c(n-3t,t)种情况(可以理解为将这4个点缩为1个,然后再从中选t个位置),然后相当于 ...
- [TJOI2019]唱、跳、rap和篮球_生成函数_容斥原理_ntt
[TJOI2019]唱.跳.rap和篮球 这么多人过没人写题解啊 那我就随便说说了嗷 这题第一步挺套路的,就是题目要求不能存在balabala的时候考虑正难则反,要求必须存在的方案数然后用总数减,往往 ...
- Luogu5339 [TJOI2019]唱、跳、rap和篮球 【生成函数,NTT】
当时看到这道题的时候我的脑子可能是这样的: My left brain has nothing right, and my right brain has nothing left. 总之,看到&qu ...
- [TJOI2019]唱、跳、rap和篮球——容斥原理+生成函数
先附一组sd图 然后放上原题链接 注意,队伍不同指的是喜好不同,不是人不同 先想到\(DP\),然后你会发现并没有什么优秀的状态设计,然后我们考虑容斥 设\(lim\)表示选的癌坤组数的上限,\(f_ ...
- 洛谷 P6295 - 有标号 DAG 计数(生成函数+容斥+NTT)
洛谷题面传送门 看到图计数的题就条件反射地认为是不可做题并点开了题解--实际上这题以我现在的水平还是有可能能独立解决的( 首先连通这个条件有点棘手,我们尝试把它去掉.考虑这题的套路,我们设 \(f_n ...
- HDU 6270 Marriage (2017 CCPC 杭州赛区 G题,生成函数 + 容斥 + 分治NTT)
题目链接 2017 CCPC Hangzhou Problem G 题意描述很清晰. 考虑每个家庭有且仅有$k$对近亲的方案数: $C(a, k) * C(b, k) * k!$ 那么如果在第$1$ ...
- 【loj#6503.】「雅礼集训 2018 Day4」Magic(生成函数+容斥)
题面 传送门 题解 复杂度比较迷啊-- 以下以\(n\)表示颜色总数,\(m\)表示总的卡牌数 严格\(k\)对比较难算,我们考虑容斥 首先有\(i\)对就代表整个序列被分成了\(m-i\)块互不相同 ...
- 洛谷P5206 [WC2019] 数树(生成函数+容斥+矩阵树)
题面 传送门 前置芝士 矩阵树,基本容斥原理,生成函数,多项式\(\exp\) 题解 我也想哭了--orz rqy,orz shadowice 我们设\(T1,T2\)为两棵树,并定义一个权值函数\( ...
- [TJOI2019]唱,跳,rap,篮球(生成函数,组合数学,NTT)
算是补了个万年大坑了吧. 根据 wwj 的题解(最准确),设一个方案 \(S\)(不一定合法)的鸡你太美组数为 \(w(S)\). 答案就是 \(\sum\limits_{S}[w(S)=0]\). ...
随机推荐
- JavaScript (内置对象及方法)
JavaScript中的对象分为3种:内置对象.浏览器对象.自定义对象 JavaScript 提供多个内置对象:Math/Array/Number/String/Boolean... 对象只是带有属性 ...
- Python——pip的安装与使用
pip 是 Python 包管理工具,该工具提供了对Python 包的查找.下载.安装.卸载的功能.目前如果你在 python.org 下载最新版本的安装包,则是已经自带了该工具.Python 2.7 ...
- H5之拖拽
步骤: 1.为将要拖拽的元素设置允许拖拽,并赋予dragstart事件将其id转换成数据保存: 2.为容器添加dragover属性添加事件阻止浏览器默认事件,允许元素放置,并赋予drop事件进行元素的 ...
- git命令——git log
功能 在提交了若干更新,又或者克隆了某个项目之后,你也许想回顾下提交历史. 完成这个任务最简单而又有效的方法是 使用git log 命令. 参数 不带任何参数 $ git log commit ca8 ...
- Vue + SpringBoot 前后端分离打包部署遇到的坑
1. 在vue项目的目录下,用npm run build 生成dist目录,将目录下的static和index.html复制到SpringBoot项目下的resource目录下 这个时候发现启动Spr ...
- unity和lua开发游戏常备技能
推荐阅读: 我的CSDN 我的博客园 QQ群:704621321 我的个人博客 一.使用制作滑动列表:使用UILayout做虚拟列表 ui.list = base:findcom(" ...
- 拦截器(Interceptor)和过滤器(Filter)的执行顺序和区别
一.引言 本来想记录一下关于用户登陆和登陆之后的权限管理.菜单管理的问题,想到解决这个问题用到Interceptor,但想到了Interceptor,就想到了Filter,于是就想说一下它们的执行顺序 ...
- python3 excel基本操作及格式设置
#encoding=utf-8 ''' excel基本操作整理 ''' #openpyxl 版本2.5.4 from openpyxl import * import datetime as dt f ...
- 猜数游戏-人机对战-经典的randint使用
翻阅去年的笔记,老师曾经教的random模块下的三种用法,其中之一是randint用法,今天上传,留作笔记参考.人生苦短,我用python! # -*- coding: UTF-8 -*- impor ...
- python模拟双色球大乐透生成算法
每天练习一段python代码,健康生活一辈子.晚上下班没事,打开电脑继续编写python代码!今天分享的一个是大家熟悉的双色球彩票的游戏,根据这个进行写的一个python算法,代码精简,肯定有bug, ...