【XSY3156】简单计数II 容斥 DP
题目大意
定义一个序列的权值为:把所有相邻的相同的数合并为一个集合后,所有集合的大小的乘积。
特别的,第一个数和最后一个数是相邻的。
现在你有 \(n\) 种数,第 \(i\) 种有 \(c_i\) 个。求所有不同的序列的权值的和。
\(n\leq 50,c_i\leq 100\)
题解
考虑第一个数和最后一个数不相邻时怎么做。
记 \(g_{i,j}\) 为出现了 \(i\) 次的数分成 \(j\) 个集合,所有集合大小的乘积的和。
\]
假设最后 \(i\) 分成了 \(a_i\) 个集合,那么答案就是 \(\prod_{i=1}^ng_{c_i,a_i}\) 再乘上方案数。
方案数可以容斥求。
具体来说,把最后相邻且同色的球合并成一个大球。设最后有 \(b_i\) 个大球,那么容斥系数就是 \({(-1)}^{a_i-b_i}\),带容斥系数的方案数就是 \(\binom{a_i-1}{b_i-1}{(-1)}^{a_i-b_i}\)
最后这 \(\sum b_i\) 个球可以随意放,方案数是 \(\frac{(\sum b_i)!}{\prod b_i!}\)
总的答案是
\]
这样就可以 DP 了。(状态为 \(i\) 和 \(\sum b_i\))
考虑第一个数和最后一个数相邻时怎么做。
可以用最小表示法,令第一个数为 \(1\) 且 最后一个数不为 \(1\)(除非 \(n=1\))。
只需要在后面计算组合数的时候把 \(b_1-1\) 再除以 \(a_1\) 就可以得到第一个数为 \(1\) 的方案数。
把 \(b_1-2\) 再除以 \(a_1\) 就可以得到第一个数为 \(1\) 且最后一个数也是 \(1\) 的方案数。
除以 \(a_1\) 是因为一个方案会被算多次。
再把方案数乘以 \(\sum c_i\) 就是答案了。
时间复杂度:\(O((\sum c_i)^2)\)
代码
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
const ll p=1000000007;
ll fac[5010],ifac[5010],inv[5010];
ll f[60][5010];
ll g[110][110];
int a[60];
int n;
int s[60];
ll c[110][110];
ll c1[110],c2[110];
ll binom(int x,int y)
{
return x>=y&&y>=0?fac[x]*ifac[y]%p*ifac[x-y]%p:0;
}
int main()
{
#ifndef ONLINE_JUDGE
freopen("c.in","r",stdin);
freopen("c.out","w",stdout);
#endif
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
s[i]=s[i-1]+a[i];
}
inv[1]=fac[0]=fac[1]=ifac[0]=ifac[1]=1;
for(int i=2;i<=5000;i++)
{
inv[i]=-p/i*inv[p%i]%p;
fac[i]=fac[i-1]*i%p;
ifac[i]=ifac[i-1]*inv[i]%p;
}
g[0][0]=1;
for(int i=1;i<=100;i++)
for(int j=1;j<=100;j++)
for(int k=1;k<=i;k++)
g[i][j]=(g[i][j]+g[i-k][j-1]*k)%p;
f[0][0]=1;
for(int i=1;i<n;i++)
for(int j=1;j<=a[i];j++)
for(int k=1;k<=j;k++)
c[i][k]=(c[i][k]+g[a[i]][j]*binom(j-1,k-1)%p*((j-k)&1?-1:1))%p;
for(int i=n;i<=n;i++)
for(int j=1;j<=a[i];j++)
for(int k=1;k<=j;k++)
c1[k]=(c1[k]+g[a[i]][j]*binom(j-1,k-1)%p*((j-k)&1?-1:1)*inv[j])%p;
for(int i=1;i<=n;i++)
for(int j=1;j<=a[i];j++)
for(int k=0;k<=s[i-1];k++)
f[i][k+j]=(f[i][k+j]+f[i-1][k]*c[i][j]%p*binom(k+j,k))%p;
ll ans=0;
for(int j=1;j<=a[n];j++)
for(int k=0;k<=s[n-1];k++)
ans=(ans+f[n-1][k]*c1[j]%p*(binom(k+j-1,k)-binom(k+j-2,k)))%p;
ans=ans*s[n]%p;
ans=(ans+p)%p;
printf("%lld\n",ans);
return 0;
}
【XSY3156】简单计数II 容斥 DP的更多相关文章
- 【BZOJ2839】集合计数(容斥,动态规划)
[BZOJ2839]集合计数(容斥,动态规划) 题面 BZOJ 权限题 Description 一个有N个元素的集合有2^N个不同子集(包含空集),现在要在这2^N个集合中取出若干集合(至少一个),使 ...
- [CF1086E]Beautiful Matrix(容斥+DP+树状数组)
给一个n*n的矩阵,保证:(1)每行都是一个排列 (2)每行每个位置和上一行对应位置不同.求这个矩阵在所有合法矩阵中字典序排第几.考虑类似数位DP的做法,枚举第几行开始不卡限制,那么显然之前的行都和题 ...
- $bzoj2560$ 串珠子 容斥+$dp$
正解:容斥+$dp$ 解题报告: 传送门$QwQ$ $umm$虽然题目蛮简练的了但还是有点难理解,,,我再抽象一点儿,就说有$n$个点,点$i$和点$j$之间有$a_{i,j}$条无向边可以连,问有多 ...
- 知识点简单总结——minmax容斥
知识点简单总结--minmax容斥 minmax容斥 好像也有个叫法叫最值反演? 就是这样的一个柿子: \[max(S) = \sum\limits_{ T \subseteq S } min(T) ...
- HDU 5794 A Simple Chess (容斥+DP+Lucas)
A Simple Chess 题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5794 Description There is a n×m board ...
- 【BZOJ3622】已经没有什么好害怕的了 容斥+DP
[BZOJ3622]已经没有什么好害怕的了 Description Input Output Sample Input 4 2 5 35 15 45 40 20 10 30 Sample Output ...
- bzoj3782上学路线(Lucas+CRT+容斥DP+组合计数)
传送门:https://www.lydsy.com/JudgeOnline/problem.php?id=3782 有部分分的传送门:https://www.luogu.org/problemnew/ ...
- [HAOI2017]方案数[组合计数、容斥、dp]
题意 题目链接 分析 先考虑没有障碍怎么做,定义 f(i,j,k) 每一维走了 i,j,k 位的方案数,转移乘个组合数即可. 现在多了一些障碍,考虑容斥.实际我们走过的点都有严格的大小关系,所以先把所 ...
- bzoj2839 集合计数(容斥)
2839: 集合计数 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 883 Solved: 490[Submit][Status][Discuss] ...
随机推荐
- gitbook 入门教程之发布电子书
输出目标文件 语法格式: gitbook build [book] [output] 默认情况下,gitbook 输出方式是静态网站,其实 gitbook 的输出方式有三种: website, jso ...
- System.map文件的作用
有关System.map文件的信息好象很缺乏.其实它一点也不神秘,并且在整个事情当中它并不象看上去那么得重要.但是由于缺乏必要的文档说明,使其显得比较神秘.它就象耳垂,我们每个人都有,但却不知道是干什 ...
- Linux(Deepin 15.9) - MySQL5.7 安装
Linux(Deepin 15.9) - MySQL5.7 安装 sudo apt install mysql-server/panda sudo apt install mysql-client/p ...
- 列表、enumerate()函数,以及查看数据类型所有的内置方法
随便看看 """ forList(): 测试list和enumerate()函数 examineFun(): 查看数据类型所有的内置方法 ""&quo ...
- jsp 简单下载
<%@ page language="java" import="java.util.*" contentType="text/html;cha ...
- 【记录】文件加密软件 Gilisoft File Lock Pro v11.0 中文注册版
---恢复内容开始--- GiliSoft File Lock Pro 是一款优秀的加密工具,用它可以隐藏或加密文件.文件夹.磁盘分区,而且被加密的文件不会因为被加密(忘记密码)而丢失,可算是很安全的 ...
- python 3.7 配置mysql数据库
一. mysql驱动安装 1.mysqlclient(推荐使用) 2.pymysql 二.django操作数据库 1.django配置连接数据库 settings.py ...
- Django REST framework框架介绍和基本使用
Django REST framework介绍 Django REST framework是基于Django实现的一个RESTful风格API框架,能够帮助我们快速开发RESTful风格的API. 官 ...
- 【English】20190312
tokens记号 [ˈtoʊkən] delimiter characters分隔符字符 [dɪ'lɪmɪtə] [ˈkærɪktɚs] argument论据主题[ˈɑ:rgjumənt] ...
- VS 附加到进程 加载“附加进程”弹窗很慢
最近遇到一个问题,点击Ctrl + Alt + P 附加到进程的时候,弹出下图弹窗“附加到进程”很慢. 找了很多原因,后来发现,是因为少安装了一个插件,安装后,弹窗的耗时明显少了. 下载 Win ...