题目


分析(弱化版)

最暴力的想法就是直接维护每种颜色的个数dp,

弱化版有一个很突出的地方就是 \(c_i\leq 5\),

也就是说可以将相同个数的颜色合并按照个数dp,

设 \(dp[c1][c2][c3][c4][c5][las]\) 表示个数为 \(i\) 的颜色有 \(ci\) 种,并且上一次选了个数为 \(las\) 的颜色的方案数

也就是这次如果选了 \(las-1\) 要减掉一个相邻的情况,转移可以记忆化。


代码

#include <cstdio>
using namespace std;
const int N=16,mod=1000000007;
int n,c[5],dp[N][N][N][N][N][5],ans;
int mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int Dp(int c0,int c1,int c2,int c3,int c4,int las){
if (dp[c0][c1][c2][c3][c4][las]) return dp[c0][c1][c2][c3][c4][las];
int ans=0;
if (c0) ans=mo(ans,1ll*(c0-(las==1))*Dp(c0-1,c1,c2,c3,c4,0)%mod);
if (c1) ans=mo(ans,1ll*(c1-(las==2))*Dp(c0+1,c1-1,c2,c3,c4,1)%mod);
if (c2) ans=mo(ans,1ll*(c2-(las==3))*Dp(c0,c1+1,c2-1,c3,c4,2)%mod);
if (c3) ans=mo(ans,1ll*(c3-(las==4))*Dp(c0,c1,c2+1,c3-1,c4,3)%mod);
if (c4) ans=mo(ans,1ll*(c4-(las==5))*Dp(c0,c1,c2,c3+1,c4-1,4)%mod);
return dp[c0][c1][c2][c3][c4][las]=ans;
}
int main(){
scanf("%d",&n);
for (int i=1,x;i<=n;++i)
scanf("%d",&x),++c[x-1];
for (int i=0;i<5;++i) dp[0][0][0][0][0][i]=1;
if (c[0]) ans=mo(ans,1ll*c[0]*Dp(c[0]-1,c[1],c[2],c[3],c[4],0)%mod);
if (c[1]) ans=mo(ans,1ll*c[1]*Dp(c[0]+1,c[1]-1,c[2],c[3],c[4],1)%mod);
if (c[2]) ans=mo(ans,1ll*c[2]*Dp(c[0],c[1]+1,c[2]-1,c[3],c[4],2)%mod);
if (c[3]) ans=mo(ans,1ll*c[3]*Dp(c[0],c[1],c[2]+1,c[3]-1,c[4],3)%mod);
if (c[4]) ans=mo(ans,1ll*c[4]*Dp(c[0],c[1],c[2],c[3]+1,c[4]-1,4)%mod);
return !printf("%d",ans);
}

分析(加强版)

在牛客的题目里,\(k,c_i\leq 30\),似乎有点棘手,考虑一个一个颜色填入序列。

设 \(dp[i][j]\) 表示前 \(i\) 种颜色有 \(j\) 个相邻的同色块的方案数。

枚举将这种颜色分成 \(k\) 段,以及选择 \(o\) 段破坏原来的相邻的同色块。那么

\[dp[i][j+c_i-k-o]=\sum dp[i-1][j]*\binom{c_i-1}{k-1}*\binom{j}{o}*\binom{s_{i-1}+1-j}{k-o}
\]

代码

#include <cstdio>
#include <cctype>
#include <cstring>
using namespace std;
const int N=31,M=911,mod=1000000007;
int a[N],s[N],c[M][M],dp[N][M],n;
int iut(){
int ans=0; char c=getchar();
while (!isdigit(c)) c=getchar();
while (isdigit(c)) ans=ans*10+c-48,c=getchar();
return ans;
}
int mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
int main(){
c[0][0]=1;
for (int i=1;i<M;++i){
c[i][0]=c[i][i]=1;
for (int j=1;j<i;++j)
c[i][j]=mo(c[i-1][j-1],c[i-1][j]);
}
for (int T=iut();T;--T){
n=iut();
for (int i=1;i<=n;++i) a[i]=iut(),s[i]=s[i-1]+a[i];
memset(dp,0,sizeof(dp)),dp[1][a[1]-1]=1;
for (int i=2;i<=n;++i)
for (int j=0;j<=s[i-1];++j)
if (dp[i-1][j]){
for (int k=1;k<=a[i];++k) for (int o=0;o<=k&&o<=j;++o)
dp[i][j+a[i]-k-o]=mo(dp[i][j+a[i]-k-o],1ll*dp[i-1][j]*c[a[i]-1][k-1]%mod*c[s[i-1]+1-j][k-o]%mod*c[j][o]%mod);
}
printf("%d\n",dp[n][0]);
}
return 0;
}

#线性dp,排列组合#洛谷 2476 [SCOI2008]着色方案的更多相关文章

  1. BZOJ1079或洛谷2476 [SCOI2008]着色方案

    一道记忆化搜索 BZOJ原题链接 洛谷原题链接 发现对于能涂木块数量一样的颜色在本质上是一样的,所以可以直接压在一个状态,而这题的数据很小,直接暴力开\(6\)维. 定义\(f[a][b][c][d] ...

  2. 洛谷 2476 [SCOI2008]着色方案

    50%的数据满足:1 <= k <= 5, 1 <= ci <= 3 100%的数据满足:1 <= k <= 15, 1 <= ci <= 5 [题解] ...

  3. 洛谷P2507 [SCOI2008]配对 题解(dp+贪心)

    洛谷P2507 [SCOI2008]配对 题解(dp+贪心) 标签:题解 阅读体验:https://zybuluo.com/Junlier/note/1299251 链接题目地址:洛谷P2507 [S ...

  4. 【BZOJ】2111: [ZJOI2010]Perm 排列计数 计数DP+排列组合+lucas

    [题目]BZOJ 2111 [题意]求有多少1~n的排列,满足\(A_i>A_{\frac{i}{2}}\),输出对p取模的结果.\(n \leq 10^6,p \leq 10^9\),p是素数 ...

  5. 【BZOJ】4559: [JLoi2016]成绩比较 计数DP+排列组合+拉格朗日插值

    [题意]n位同学(其中一位是B神),m门必修课,每门必修课的分数是[1,Ui].B神碾压了k位同学(所有课分数<=B神),且第x门课有rx-1位同学的分数高于B神,求满足条件的分数情况数.当有一 ...

  6. G.subsequence 1(dp + 排列组合)

    subsequence 1 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 You are ...

  7. 洛谷P2756飞行员配对方案问题 P2055假期的宿舍【二分图匹配】题解+代码

    洛谷 P2756飞行员配对方案问题 P2055假期的宿舍[二分图匹配] 飞行员配对方案问题 题目背景 第二次世界大战时期.. 题目描述 英国皇家空军从沦陷国征募了大量外籍飞行员.由皇家空军派出的每一架 ...

  8. bzoj 1079: [SCOI2008]着色方案 DP

    1079: [SCOI2008]着色方案 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 803  Solved: 512[Submit][Status ...

  9. [SCOI2008] 着色方案[高维dp]

    321. [SCOI2008] 着色方案 ★★★   输入文件:color.in   输出文件:color.out   简单对比时间限制:1 s   内存限制:64 MB 题目背景: 有n个木块排成一 ...

  10. BZOJ 1079: [SCOI2008]着色方案 记忆化搜索

    1079: [SCOI2008]着色方案 Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/p ...

随机推荐

  1. ADVMP 三代壳(vmp加固)原理分析(加壳流程)

    开源项目地址 https://github.com/chago/ADVMP vmp 加固可以说时各大加固厂商的拳头产品了,这个开源项目虽然不是十分完善,让我们可以一览vmp加固的原理,是十分好的学习资 ...

  2. C C++结构体四种方式

    第一种语法表示 struct 结构体名称 {     数据类型 member1:     数据类型 member2;  };  #include<iostream> using names ...

  3. sql组合索引怎样使用?怎样命中?

    一.联合索引的使用 本文中联合索引的定义为(MySQL): ALTER TABLE table_name ADD INDEX (col1,col2,col3); 二.联合索引的本质 当创建(col1, ...

  4. Java纯手打web服务器(一)

    目录 在主线程中进行等待客户端请求: 这里主要说下解析流程: 在主线程中进行等待客户端请求: public static void main(String[] args) { HttpServer1 ...

  5. 开源短信项目 platform-sms 发布了新版本 0.5.0

    Github : https://github.com/makemyownlife/platform-sms 短信服务 platform-sms 0.5.0 发布 ,新的版本做了非常多的优化和改进. ...

  6. vim技巧--提取文本与文本替换

    前几天遇到一个使用情景,需要从一个包含各个读取代码文件路径及名字的文件中把文件路径提取出来,做一个filelist,这里用到了文本的提取和替换,这里做个小总结记录一下. 从网上找了一个作者写的代码用来 ...

  7. isNumber 数字正则校验 表达式

    isNumber 数字正则校验 表达式 isNumber(value) { return (/(^-?[0-9]+\.{1}\d+$)|(^-?[1-9][0-9]*$)|(^-?0{1}$)/).t ...

  8. IP对讲广播音频模块解决方案

    需求分析   随着数字化进程的不断推进,对讲已经覆盖到了各行业各业.并且也逐渐呈现出场景分散化的特点.鉴于此,团队根据市场的变化,及时推出了一款标准化的模块,方便系统集成厂商集成和运用,从而达到节省开 ...

  9. opus编解码的特色和优点

    概念原理   Opus是一个有损音频压缩的数字音频编码格式,由Xiph.Org基金会开发,之后由互联网工程任务组(IETF)进行标准化,目标是希望用单一格式包含声音和语音,取代Speex和Vorbis ...

  10. AOSP源码编译—交换空间扩容

    编译AOSP源码的时候会出现提示如下: 意思是需要16G左右的内存(实际上编译会超过16G),而我们之前安装Ubuntu的时候只分配了8G,编 译一定会失败!此时需要添加虚拟内存(swap交换空间) ...