小w的喜糖(candy)
小w的喜糖(candy)
题目描述
废话不多说,反正小w要发喜糖啦!!
小w一共买了n块喜糖,发给了n个人,每个喜糖有一个种类。这时,小w突发奇想,如果这n个人相互交换手中的糖,那会有多少种方案使得每个人手中的糖的种类都与原来不同。
两个方案不同当且仅当,存在一个人,他手中的糖的种类在两个方案中不一样。
输入
第一行,一个整数n。
接下来n行,每行一个整数,第i个整数Ai表示开始时第i个人手中的糖的种类。
输出
一行,一个整数Ans,表示方案数模1000000009。
样例输入
6
1
1
2
2
3
3
样例输出
10
提示
【数据规模和约定】
对于所有数据,1≤Ai≤k。
数据点 |
n |
k |
约束 |
1 |
≤10 |
≤10 |
无 |
2 |
|||
3 |
≤20 |
n |
每个人的糖果种类都不一样 |
4 |
≤100 |
||
5 |
≤2000 |
||
6 |
|||
7 |
≤200 |
3 |
无 |
8 |
|||
9 |
|||
10 |
|||
11 |
≤n |
||
12 |
|||
13 |
|||
14 |
|||
15 |
≤2000 |
||
16 |
|||
17 |
|||
18 |
|||
19 |
|||
20 |
solution
背景(没用)
错排:求1~n的排列ai,满足ai!=i的个数
考虑令
表示
个数字任意放的方案数,
表示
个数字都不放在自己位置上的方案数,通过枚举不在自己位置上的数字的个数容易得到
由二项式反演得到
注意到
,这样我们就得到了他的通项公式,通过将
和组合数展开就可以得到更为简便的通项公式了
---------------某度
有重复元素的排列
好的,接下来才是正经的题解
令f[i][j]表示前i种糖,有j个人拿到了原来的糖的方案数
考虑算f[i][j]
也就是第i种糖,有k个人不合法
就这样啦
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#define maxn 2005
#define mod 1000000009
using namespace std;
int n,cnt[maxn],t;
long long ans,ny[maxn],f[maxn][maxn],h[maxn];
long long work(long long k,long long num){
long long tmp=1;
while(num){
if(num&1)tmp=tmp*k;
k=k*k;k%=mod;tmp%=mod;num/=2;
}
return tmp;
}
long long C(int n,int m){
long long tmp=0;
tmp=(1LL*h[n]*ny[m]%mod)*ny[n-m];tmp%=mod;
return tmp;
}
int main()
{
cin>>n;
for(int i=1;i<=n;i++){
scanf("%d",&t);
cnt[t]++;
}
h[0]=1;ny[0]=1;
for(int i=1;i<=n;i++){
h[i]=(1LL*h[i-1]*i)%mod;
ny[i]=work(h[i],mod-2);
}
f[0][0]=1;
for(int i=1;i<=n;i++)
for(int j=0;j<=n;j++){
for(int k=0;k<=cnt[i];k++){
if (k>j)break;
f[i][j]+=(1LL*f[i-1][j-k]*C(cnt[i],k))%mod*ny[cnt[i]-k];
f[i][j]%=mod;
}
}
int op=1;
for(int i=0;i<=n;i++){
ans+=(1LL*f[n][i]*(h[n-i]*op))%mod;
op=op*(-1);
}
ans=(ans%mod+mod)%mod;
cout<<ans<<endl;
return 0;
}
小w的喜糖(candy)的更多相关文章
- bzoj4665小w的喜糖 dp+容斥
4665: 小w的喜糖 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 120 Solved: 72[Submit][Status][Discuss] ...
- bzoj4665 小w的喜糖(dp+容斥)
4665: 小w的喜糖 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 222 Solved: 130[Submit][Status][Discuss ...
- 【BZOJ 4665】 4665: 小w的喜糖 (DP+容斥)
4665: 小w的喜糖 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 94 Solved: 53 Description 废话不多说,反正小w要发喜 ...
- 【BZOJ4665】小w的喜糖 容斥+组合数
[BZOJ4665]小w的喜糖 Description 废话不多说,反正小w要发喜糖啦!! 小w一共买了n块喜糖,发给了n个人,每个喜糖有一个种类.这时,小w突发奇想,如果这n个人相互交换手中的糖,那 ...
- [bzoj4665]小w的喜糖_二项式反演
小w的喜糖 题目链接:https://lydsy.com/JudgeOnline/problem.php?id=4665 数据范围:略. 题解: 二项式反演裸题. $f_{i,j}$表示,前$i$种钦 ...
- BZOJ 4665: 小w的喜糖
Sol DP+容斥. 这就是一个错排的扩展...可是想到容斥却仅限于种数的容斥,如果种数在一定范围内我就会做了QAQ. 但是容斥的是一定在原来位置的个数. 发现他与原来的位置无关,可以先把每个同种的糖 ...
- ●BZOJ 4665 小w的喜糖
题链: http://www.lydsy.com/JudgeOnline/problem.php?id=4665 题解: 容斥,dp令 v[i] 表示原来拥有i类糖果的人数. (一个套路,首先把每个糖 ...
- BZOJ4665: 小w的喜糖 DP
对于这道题,首先每个人的位置并不影响结果 所以我们可以将相同颜色糖果的人放在一块处理 设 $f_{i,j}$ 表示处理到第 $i$ 种糖果至少有 $j$ 人的糖果和原先的类型相同 枚举当前种类中不满足 ...
- BZOJ4665 : 小w的喜糖
考虑枚举哪些人一定不合法,那么方案数可以通过简单的排列组合算出. 于是设$f[i][j]$表示前$i$种糖果,一共有$j$个人一定不合法的方案数,但是这样并不能保证其他人一定合法,所以需要进行容斥. ...
随机推荐
- python_78_软件目录结构规范
一定要看http://www.cnblogs.com/alex3714/articles/5765046.html #print(__file__)#打印的是文件的相对路径 import os pri ...
- icon踩坑记录
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 【前端_React】React小书
参考书籍:React.js 小书
- JS学习笔记-构造函数篇
创建实例 funtion Fn (){ var num = 10; this.x = 100; this.getX = function(){ cons ...
- 前端JS转图片为base64并压缩、调整尺寸脚本
image to base64 to blob //////////////////////////////////////////////////////////////////////////// ...
- Python知识点进阶——生成器
生成器 为什么要将列表转化为迭代器? 因为列表太大的话用内存太大,做成迭代器可以节省空间,用的时候再拿出部分. 生成器是不会把结果保存在一个系列中,而是保存生成器的状态,在每次进行迭代时返回一个值,知 ...
- C++多态实例
#include <iostream> #include <string> using namespace std; //class 实现 class Employee { s ...
- 动态规划:最长上升子序列之基础(经典算法 n^2)
解题心得: 1.注意动态转移方程式,d[j]+1>d[i]>?d[i]=d[j]+1:d[i] 2.动态规划的基本思想:将大的问题化为小的,再逐步扩大得到答案,但是小问题的基本性质要和大的 ...
- 笔记-python-反射
笔记-python-反射 1. 反射 在很多地方看到自省和反射,很晕菜,整理了一下相关文档,加深了理解. 自省和反射其实说的是一件事,核心操作是根据输入去对象(模块)中调用(查找/获取/删除/添加)成 ...
- Spark MLlib(下)--机器学习库SparkMLlib实战
1.MLlib实例 1.1 聚类实例 1.1.1 算法说明 聚类(Cluster analysis)有时也被翻译为簇类,其核心任务是:将一组目标object划分为若干个簇,每个簇之间的object尽可 ...