bzoj4665小w的喜糖 dp+容斥
4665: 小w的喜糖
Time Limit: 10 Sec Memory Limit: 128 MB
Submit: 120 Solved: 72
[Submit][Status][Discuss]
Description
废话不多说,反正小w要发喜糖啦!!
小w一共买了n块喜糖,发给了n个人,每个喜糖有一个种类。这时,小w突发奇想,如果这n个人相互交换手中的糖,那会有多少种方案使得每个人手中的糖的种类都与原来不同。
两个方案不同当且仅当,存在一个人,他手中的糖的种类在两个方案中不一样。
Input
第一行,一个整数n
接下来n行,每行一个整数,第i个整数Ai表示开始时第i个人手中的糖的种类
对于所有数据,1≤Ai≤k,k<=N,N<=2000
Output
一行,一个整数Ans,表示方案数模1000000009
Sample Input
6
1
1
2
2
3
3
Sample Output
10
f[i][j]表示前i种糖,j个人拿到的糖相同,剩下的糖果先不发给人
转移式还是挺好推的
把每种糖看成不同,b[i]表示第i种糖的个数
每新增加一种糖,枚举现在几个人拿到自己的糖 一个人拿到自己的糖要在所有同种糖中选择
转移完之后,所有f[i][j]*=fac[n-j]表示剩下的糖随意分给其他人,不保证不分到自己的糖
所以f[i][j]就变成了至少j个人拿到相同的糖,容斥一下
最后,因为把每种糖的个体视为不同,需要 /fac[b[i]]
推荐blog
http://www.cnblogs.com/zj75211/p/8035076.html
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#define ll long long
#define N 2005
#define mod 1000000009
using namespace std;
int n,m,f[N][N],a[N],b[N],fac[N],inv[N],c[N][N],sum[N];
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
sort(a+1,a+1+n);
for(int i=1;i<=n;i++){
if(a[i]!=a[i-1])m++;
b[m]++;
}
for(int i=1;i<=m;i++)
sum[i]=sum[i-1]+b[i];
for(int i=0;i<=2000;i++)
c[i][i]=c[i][0]=1;
for(int i=1;i<=2000;i++)
for(int j=1;j<i;j++)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
fac[0]=fac[1]=inv[0]=inv[1]=1;
for(int i=2;i<=2000;i++){
fac[i]=1ll*fac[i-1]*i%mod;
inv[i]=mod-1ll*(mod/i)*inv[mod%i]%mod;
}
for(int i=2;i<=2000;i++)inv[i]=1ll*inv[i]*inv[i-1]%mod;
f[0][0]=1;
for(int i=1;i<=m;i++)
for(int j=0;j<=sum[i-1];j++)
for(int k=0;k<=b[i];k++)
f[i][j+k]=(f[i][j+k]+1ll*f[i-1][j]*c[b[i]][k]%mod*fac[b[i]]%mod*inv[b[i]-k]%mod)%mod;
ll ans=0;
for(int i=n;i>=0;i--)
ans=(ans+1ll*((n-i)&1?-1:1)*f[m][i]*fac[n-i])%mod;
for(int i=1;i<=m;i++)ans=ans*inv[b[i]]%mod;
ans<0?ans+=mod:1;
cout<<ans;
return 0;
}
bzoj4665小w的喜糖 dp+容斥的更多相关文章
- BZOJ4665: 小w的喜糖 DP
对于这道题,首先每个人的位置并不影响结果 所以我们可以将相同颜色糖果的人放在一块处理 设 $f_{i,j}$ 表示处理到第 $i$ 种糖果至少有 $j$ 人的糖果和原先的类型相同 枚举当前种类中不满足 ...
- bzoj4665 小w的喜糖(dp+容斥)
4665: 小w的喜糖 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 222 Solved: 130[Submit][Status][Discuss ...
- [bzoj4665]小w的喜糖_二项式反演
小w的喜糖 题目链接:https://lydsy.com/JudgeOnline/problem.php?id=4665 数据范围:略. 题解: 二项式反演裸题. $f_{i,j}$表示,前$i$种钦 ...
- BZOJ4665 : 小w的喜糖
考虑枚举哪些人一定不合法,那么方案数可以通过简单的排列组合算出. 于是设$f[i][j]$表示前$i$种糖果,一共有$j$个人一定不合法的方案数,但是这样并不能保证其他人一定合法,所以需要进行容斥. ...
- 【BZOJ4665】小w的喜糖 容斥+组合数
[BZOJ4665]小w的喜糖 Description 废话不多说,反正小w要发喜糖啦!! 小w一共买了n块喜糖,发给了n个人,每个喜糖有一个种类.这时,小w突发奇想,如果这n个人相互交换手中的糖,那 ...
- 【BZOJ 4665】 4665: 小w的喜糖 (DP+容斥)
4665: 小w的喜糖 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 94 Solved: 53 Description 废话不多说,反正小w要发喜 ...
- BZOJ 4665: 小w的喜糖
Sol DP+容斥. 这就是一个错排的扩展...可是想到容斥却仅限于种数的容斥,如果种数在一定范围内我就会做了QAQ. 但是容斥的是一定在原来位置的个数. 发现他与原来的位置无关,可以先把每个同种的糖 ...
- bzoj 3622 DP + 容斥
LINK 题意:给出n,k,有a,b两种值,a和b间互相配对,求$a>b$的配对组数-b>a的配对组数恰好等于k的情况有多少种. 思路:粗看会想这是道容斥组合题,但关键在于如何得到每个a[ ...
- 小w的喜糖(candy)
小w的喜糖(candy) 题目描述 废话不多说,反正小w要发喜糖啦!! 小w一共买了n块喜糖,发给了n个人,每个喜糖有一个种类.这时,小w突发奇想,如果这n个人相互交换手中的糖,那会有多少种方案使得每 ...
随机推荐
- 点击tableViewCell,调用打电话的功能
对于点击tableViewCell,调用打电话的功能,按照一般的方法,使用Appdelegate的OpenUrl的方法,使用前先使用UIAlertView展示,让用户选择是否拨打,但是发现了个简单的方 ...
- python利用twilio模块给自己发短信
1.访问http://twilio.com/并填写注册表单.注册了新账户后,你需要验证一个手机号码,短信将发给该号码. 2.Twilio 提供的试用账户包括一个电话号码,它将作为短信的发送者.你将需要 ...
- Spring中报"Could not resolve placeholder"的解决方案
除去properites文件路径错误.拼写错误外,出现"Could not resolve placeholder"很有可能是使用了多个PropertyPlaceholderCon ...
- 大数据学习总结(7)we should...
大数据场景一.各种标签查询 查询要素:人.事.物.单位 查询范围:A范围.B范围.... 查询结果:pic.name.data from 1.痛点:对所有文本皆有实时查询需求2.难点:传统SQL使用W ...
- Docker学习笔记 - Docker的守护进程
学习目标: 查看Docker守护进程的运行状态 启动.停止.重启Docker守护进程 Docker守护进程的启动选项 修改和查看Docker守护进程的启动选项 1.# 查看docker运行状态 方 ...
- 阿里云API网关(6)用户指南(开放 API )
网关指南: https://help.aliyun.com/document_detail/29487.html?spm=5176.doc48835.6.550.23Oqbl 网关控制台: https ...
- 浅谈Web网站的架构演变过程
前言 我们以javaweb为例,来搭建一个简单的电商系统,看看这个系统可以如何一步步演变. 该系统具备的功能: 用户模块:用户注册和管理 商品模块:商品展示和管理 交易模块:创建交易和管理 阶 ...
- Mac 中配置Apache
使用的mac版本是10.10.1,mac自带的Apache环境 分为两部分: 1.启动Apache 2.设置虚拟主机 启动Apache 打开终端, >>sudo apachectl -v, ...
- Spring Boot面试题
Spring Boot 是微服务中最好的 Java 框架. 我们建议你能够成为一名 Spring Boot 的专家. 问题一 Spring Boot.Spring MVC 和 Spring 有什么区别 ...
- python基础——继承与派生、组合
python基础--继承与派生 1 什么是继承: 继承是一种创建新的类的方式,在python中,新建的类可以继承自一个或者多个父类,原始类成为基类或超累,新建的类成为派生类或子类 1.1 继承分为:单 ...