【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] ...
随机推荐
- 混用Int与IntPtr导致GetProcAddress始终返回null
注意NET某些类型在不同平台上的长度 NET中用句柄用得最多的是在DLLIMPORT中,混用int与intptr可能会导致某些API声明在X64平台中表现不正常,如 [DllImport(&quo ...
- win10系统下安装MySQLdb和pymysql
(1)使用的是Python3.6,想要使用MySQLdb, 需要先在https://www.lfd.uci.edu/~gohlke/pythonlibs/#mysqlclient中下载相应版本的包 ...
- 探究高级的Kotlin Coroutines知识
要说程序如何从简单走向复杂, 线程的引入必然功不可没, 当我们期望利用线程来提升程序效能的过程中, 处理线程的方式也发生了从原始时代向科技时代发生了一步一步的进化, 正如我们的Elisha大神所著文章 ...
- [Python][小知识][NO.5] 使用 Pyinstaller 打包成.exe文件
1.安装 pyinstaller 插件 cmd命令:pip install PyInstaller PS . o.o 不知道 easy_install 的百度吧. 2.pyinstaller 简介 他 ...
- 【iOS开发】Alamofire框架的使用一基本用法
Alamofire框架的使用一 —— 基本用法 对于使用Objective-C的开发者,一定非常熟悉AFNetworking这个网络框架.在苹果推出的Swift之后,AFNetworking的作者专门 ...
- C# groupby 应用小技巧
这两天感冒了,导致大脑无法有效运转,一个朋友问我,groupby 怎么给list 分组,然后再将其中一个字段组合起来,恩,觉得很简单,结果才发现,自己的脑子真的是不够用了: 恩,其实是想写其他的,但是 ...
- vue li click
<ul> <li @click="mechanisms(1)">AAAAA</li> <li @click=" ...
- 利用BLKTRACE分析IO性能
在Linux系统上,如果I/O发生性能问题,有没有办法进一步定位故障位置呢?iostat等最常用的工具肯定是指望不上的,[容易被误读的iostat]一文中解释过await表示单个I/O所需的平均时间, ...
- Node+express实现后台服务接口
一.准备工作 创建代码目录,依次执行以下操作 1.(若没有安装过)安装node 2.npm init(package.json) 3.安装express(请求)npm install express ...
- SQL SUM() 函数
SUM() 函数 SUM 函数返回数值列的总数(总额). SQL SUM() 语法 SELECT SUM(column_name) FROM table_name SQL SUM() 实例 我们拥有下 ...