用$m$种颜色的彩球装点$n$层的圣诞树。圣诞树的第$i$层恰由$a_{i}$个彩球串成一行,且同一层内的相邻彩球颜色不同,同时相邻两层所使用彩球的颜色集合不 同。求有多少种装点方案,答案对$p$取模。

好神的计数问题,zwz Orz

题解思路来自黄学长hzwer的博客

先只考虑在一行内的彩球的方案数

定义$g[i][j]$表示一共有$i$个球串成一行,一共用了$j$种颜色的方案数

因为所有颜色都是等价的,我们可以利用最小表示法来简化计数,比如让颜色编号为$x+1$的球第一次出现的位置,在颜色编号为$x$的球之前。实际的方案数是$g[i][j]\cdot j!$

这样递推关系就简单多了

加入一个新颜色的球,$g[i][j]+=g[i-1][j-1]$

加入一个旧颜色的球,颜色不能和第$i-1$个球相同,$g[i][j]+=(j-1)g[i-1][j]$

$g[i][j]=g[i-1][j-1]+(j-1)g[i-1][j]$

在考虑行行之间的影响

定义$f[i][j]$表示前$i$行,其中第$i$行选了$j$种颜色的方案数

如果没有相邻两行集合不同这种限制

$f[i][j]=C_{m}^{j}\cdot g[a_{i}][j]\cdot \sum f[i-1][k]$

如果加上限制,

$f[i][j]=C_{m}^{j}\cdot g[a_{i}][j]\cdot j!\sum f[i-1][k]-g[a_{i}][j]\cdot j!\cdot f[i-1][j]$

$=A_{m}^{j}\cdot g[a_{i}][j]\sum f[i-1][k]-g[a_{i}][j]\cdot j!\cdot f[i-1][j]$

利用前缀和优化可以$O(1)$转移

$f[i][j]$的状态数也仅仅是$O(\sum a_{i})$,用滚动数组记录

$A_{m}^{j}$和$j!$可以通过预处理得到

总结:由于本题的模数是非质数,用组合数计数会让问题变得复杂,且时间复杂度很难保证。如果本题保证模数为质数,可能会有很多其他做法,比如组合数+容斥等等,但应该都没有官方题解的思路简洁。出题者似乎引导我们走向突破口——消去组合数,突破口在于通过化简,把组合数化成排列数和阶乘,排列数和阶乘即使在模数为非质数的情况下,也能在$O(n)$时间预处理

 #include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define N1 5010
#define M1 1000010
#define dd double
#define ll long long
using namespace std; int gint()
{
int ret=,fh=;char c=getchar();
while(c<''||c>''){if(c=='-')fh=-;c=getchar();}
while(c>=''&&c<=''){ret=ret*+c-'';c=getchar();}
return ret*fh;
}
int n,m,mx,P; int f[][N1],g[N1][N1],am[N1],mul[N1],a[M1]; int main()
{
int i,j,x;
scanf("%d%d%d",&n,&m,&x);
for(i=;i<=n;i++) scanf("%d",&a[i]), mx=max(mx,a[i]);
const int p=x;
g[][]=g[][]=;
for(i=;i<=mx;i++) for(j=;j<=i;j++) g[i][j]=(1ll*(j-)*g[i-][j]%p+g[i-][j-])%p;
mul[]=mul[]=; am[]=;
for(i=;i<=min(m,mx);i++) am[i]=1ll*am[i-]*(m-i+)%p;
for(i=;i<=mx;i++) mul[i]=1ll*mul[i-]*i%p;
int now=,pst=,snow=,spst=;
f[pst][]=;
for(i=;i<=n;i++)
{
snow=;
for(j=;j<=min(m,a[i]);j++)
f[now][j]=(1ll*am[j]*g[a[i]][j]%p*spst%p-1ll*f[pst][j]*mul[j]%p*g[a[i]][j]%p+p)%p, (snow+=f[now][j])%=p;
memset(f[pst],,(min(m,a[i-])+)<<);
swap(now,pst); swap(snow,spst);
}
printf("%d\n",spst);
return ;
}

CF140E New Year Garland (计数问题)的更多相关文章

  1. [cf140e]New Year Garland

    Description 用$m$种颜色的彩球装点$n$层的圣诞树.圣诞树的第$i$层恰由$l[i]$个彩球串成一行,且同一层内的相邻彩球颜色不同,同时相邻两层所使用彩球的颜色集合不同. 求有多少种装点 ...

  2. 一些gcd计数问题

    数论什么的全都忘光了吧QAQ 做了几道简单的题练习一下. bzoj1101: [POI2007]Zap 求有多少对数满足 gcd(x,y)=d, 1<=x<=a, 1<=y<= ...

  3. POJ 1759 Garland(二分+数学递归+坑精度)

    POJ 1759 Garland  这个题wa了27次,忘了用一个数来储存f[n-1],每次由于二分都会改变f[n-1]的值,得到的有的值不精确,直接输出f[n-1]肯定有问题. 这个题用c++交可以 ...

  4. poj 1759 Garland (二分搜索之其他)

    Description The New Year garland consists of N lamps attached to a common wire that hangs down on th ...

  5. 扩展Python模块系列(四)----引用计数问题的处理

    承接上文,发现在使用Python C/C++ API扩展Python模块时,总要在各种各样的地方考虑到引用计数问题,稍不留神可能会导致扩展的模块存在内存泄漏.引用计数问题是C语言扩展Python模块最 ...

  6. poj 1759 Garland

    Garland Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 2365   Accepted: 1007 Descripti ...

  7. 置换群、Burnside引理与等价类计数问题

    置换群.Burnside引理与等价类计数问题 标签: 置换群 Burnside引理 置换 说说我对置换的理解,其实就是把一个排列变成另外一个排列.简单来说就是一一映射.而置换群就是置换的集合. 比如\ ...

  8. C. Nice Garland Codeforces Round #535 (Div. 3) 思维题

    C. Nice Garland time limit per test 1 second memory limit per test 256 megabytes input standard inpu ...

  9. D. Diverse Garland Codeforces Round #535 (Div. 3) 暴力枚举+贪心

    D. Diverse Garland time limit per test 1 second memory limit per test 256 megabytes input standard i ...

随机推荐

  1. codevs——T1169 传纸条

    http://codevs.cn/problem/1169/  时间限制: 1 s  空间限制: 128000 KB  题目等级 : 钻石 Diamond 题解  查看运行结果     题目描述 De ...

  2. ps -ef与ps aux的区别

    ps -ef与ps aux的区别 学习:http://www.linuxidc.com/Linux/2016-07/133515.htm ps aux可以查看其内存使用情况:

  3. ftk学习记(label篇)

    [ 声明:版权全部,欢迎转载,请勿用于商业用途.  联系信箱:feixiaoxing @163.com] 还是接着上面的一篇博文. 之前以前答应过大家,让大家看一下最简单的ftk程序是怎么执行的.所以 ...

  4. 《从零開始学Swift》学习笔记(Day48)——类型检查与转换

    原创文章,欢迎转载.转载请注明:关东升的博客 继承会发生在子类和父类之间,是一系列类的继承关系. 比如:Person是类层次结构中的根类.Student是Person的直接子类.Worker是Pers ...

  5. [Linux]非常方便的上传下载文件工具rz和sz

     linux上非常方便的上传下载文件工具rz和sz (本文适合linux入门的朋友) [一般用于SecureCRT ssh中使用] █ 法一:直接用yum安装lrzsz(推荐) yum insta ...

  6. wpf Textbox 点击选中全部文本

    用法:依赖属性 SelectTextOnFocus.Active = True public class SelectTextOnFocus : DependencyObject { public s ...

  7. hdu1829 A Bug&#39;s Life(并查集)

    开两个并查集.然后合并的时候要合并两次.这样在合并之前推断是否冲突,假设不冲突就进行合并,否则不须要继续合并. #include<cstdio> #include<cstdlib&g ...

  8. [ACM] HDU 5086 Revenge of Segment Tree(全部连续区间的和)

    Revenge of Segment Tree Problem Description In computer science, a segment tree is a tree data struc ...

  9. linux Redis 5.0集群搭建

    文档结构如下: Redis cluster 是redis的分布式解决方案,在3.0版本正式推出后,有效的解决了redis分布式方面的需求:当遇到单机内存,并发,流量等瓶颈是,可以采用cluster架构 ...

  10. Android网络编程随想录(1)

    本系列文章对整个Android网络编程进行了总结,包括基本的TCP/IP协议,HTTP协议,HTTPS协议,HttpClient,UrlConnection,一些网络通信的库到棉花糖新加入的OKHTT ...