BZOJ1079 [SCOI2008]着色方案[组合计数DP]
$有a_{1}个1,a_{2}个2,...,a_{n}个n(n<=15,a_{n}<=5),求排成一列相邻位不相同的方案数。$
关于这题的教训记录:
- 学会对于复杂的影响分开计,善于发现整体变化,用整体法(没错就是和物理那种差不多)。
- 推dp方程时怕边界问题不好处理时可以采用向前推的方法,就如$f[x]=f[i]+...$,可以(部分)避免越界。
我好菜啊。。除了个dp状态设计对了其他什么都没写上来qwq。基于每次插入时数字的数量都不固定,所以我可以设法将其固定下来。按顺序依次插入1,2,3,...,n即可。因为我是要统计相同不相邻方案,转移的时候肯定是插空啊,所以再设计一维表示有多少个相邻相同的($f[i][j]$),这样就好做了。然而我在这里卡主了。。因为我看数据每个数字最多5个嘛,分类大力讨论一下的事情。然而讨论到3的时候我已经崩溃掉了。觉得写法有问题,但是又不知道怎么简化。
磕了几小时没出来QwQ,翻了题解%%%,发现还是思路狭窄了啊。每个数k个,因为要往空挡里面插,不算几张合在一起的话,分开的情况是很容易想的。而我有连续数字插入的时候,可以枚举其分组。分k组的时候,这些牌单独来看是会产生出新的$n-k$个连续位的。再看我插入时,把连续数字当做整体(就是看成一个数字),插入之前的连续位空挡相当于把他填起来了,否则无影响。所以枚举插到数字$i$,枚举之前有$j$空位连续数字,当下分为$k$组,插到之前$j$个空位里的有$l$个,之前方案$f[i][j]$,$j$个空位中选出来$l$个是$C_{j}^{l}$,剩下的非连续数字的空位还要再选$C_{sum[i-1]+1-j}^{k-l}$个,这些空位里去填$k$组,问题转为一排数字划为k组的不同方案,是经典隔板问题,有$C_{a[i]-1}^{k-1}$种。所以dp方程就出来啦。见code。可以感性认识这是不重不漏的。(??!)
可能我组合计数还是太差了啊。几星期后到数学专题去好好补一发算了。。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define dddbg(x,y,z) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<" "<<#z<<" = "<<z<<endl
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const ll P=1e9+;
int f[][],fac[],C[][];
int T,n,s[],sum[];
inline void inc(int&A,int B){A+=B;A>=P?A-=P:;}
inline void preprocess(){
C[][]=;
for(register int i=;i<=;++i){C[i][]=;for(register int j=;j<=;++j)C[i][j]=(0ll+C[i-][j]+C[i-][j-])%P;}
} int main(){//freopen("test.in","r",stdin);freopen("test.out","w",stdout);
preprocess();read(n);
for(register int i=;i<=n;++i)read(s[i]);
f[][s[]-]=;
for(register int i=;i<=n;++i)sum[i]=s[i]+sum[i-];
for(register int i=;i<=n;++i)
for(register int j=;j<=sum[i-]-i+;++j)
for(register int k=;k<=s[i];++k)
for(register int l=;l<=_min(j,k);++l)
inc(f[i][j+s[i]-k-l],f[i-][j]*1ll*C[j][l]%P*C[sum[i-]+-j][k-l]%P*C[s[i]-][k-]%P);
printf("%d\n",f[n][]);
return ;
}
hihocoder扑克牌:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<queue>
#define dbg(x) cerr<<#x<<" = "<<x<<endl
#define dddbg(x,y,z) cerr<<#x<<" = "<<x<<" "<<#y<<" = "<<y<<" "<<#z<<" = "<<z<<endl
using namespace std;
typedef unsigned long long ull;
typedef pair<int,int> pii;
template<typename T>inline char MIN(T&A,T B){return A>B?A=B,:;}
template<typename T>inline char MAX(T&A,T B){return A<B?A=B,:;}
template<typename T>inline T _min(T A,T B){return A<B?A:B;}
template<typename T>inline T _max(T A,T B){return A>B?A:B;}
template<typename T>inline T read(T&x){
x=;int f=;char c;while(!isdigit(c=getchar()))if(c=='-')f=;
while(isdigit(c))x=x*+(c&),c=getchar();return f?x=-x:x;
}
const int N=;
ull f[N][],fac[],C[][];
int T,n,cnt[N],s[N],sum[N];
char ch[]; int main(){//freopen("test.in","r",stdin);freopen("test.out","w",stdout);
read(T);fac[]=,fac[]=,fac[]=,fac[]=;C[][]=;
for(register int i=;i<=;++i){
C[i][]=;
for(register int j=;j<=;++j)C[i][j]=C[i-][j]+C[i-][j-];
}
for(register int o=;o<=T;++o){
read(n);memset(cnt,,sizeof cnt);
for(register int i=;i<=n;++i){
scanf("%s",ch+);int x=ch[]&;
if(ch[]=='A')x=;else if(ch[]=='T')x=;else if(ch[]=='J')x=;else if(ch[]=='Q')x=;else if(ch[]=='K')x=;
++cnt[x];
}n=;
for(register int i=;i<=;++i)if(cnt[i])s[++n]=cnt[i],sum[n]=s[n]+sum[n-];
memset(f,,sizeof f);f[][s[]-]=;
for(register int i=;i<=n;++i)
for(register int j=;j<=sum[i-]-i+;++j)
for(register int k=;k<=s[i];++k)
for(register int l=;l<=_min(j,k);++l)
f[i][j+s[i]-k-l]+=f[i-][j]*C[j][l]*C[sum[i-]+-j][k-l]*C[s[i]-][k-];
for(register int i=;i<=n;++i)f[n][]*=fac[s[i]];
printf("Case #%d: %llu\n",o,f[n][]);
}
return ;
}
BZOJ1079 [SCOI2008]着色方案[组合计数DP]的更多相关文章
- BZOJ1079:[SCOI2008]着色方案(DP)
Description 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个 ...
- BZOJ1079 [SCOI2008]着色方案 【dp记忆化搜索】
题目 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+-+ck=n.相邻两个木块涂相同色显得很难看 ...
- [luogu2476][bzoj1079][SCOI2008]着色方案【动态规划】
题目描述 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块.所有油漆刚好足够涂满所有木块,即c1+c2+-+ck=n.相邻两个木块涂相同色显得很难 ...
- BZOJ1079 [SCOI2008]着色方案 动态规划
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ1079 题目概括 有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的 ...
- BZOJ1079: [SCOI2008]着色方案 (记忆化搜索)
题意:有n个木块排成一行,从左到右依次编号为1~n.你有k种颜色的油漆,其中第i种颜色的油漆足够涂ci个木块. 所有油漆刚好足够涂满所有木块,即c1+c2+...+ck=n.相邻两个木块涂相同色显得很 ...
- 2018.10.20 bzoj1079: [SCOI2008]着色方案(多维dp)
传送门 dp妙题. f[a][b][c][d][e][last]f[a][b][c][d][e][last]f[a][b][c][d][e][last]表示还剩下aaa个可以用一次的,还剩下bbb个可 ...
- bzoj1079: [SCOI2008]着色方案
dp.以上次染色时用的颜色的数量和每种数量所含有的颜色作状态. #include<cstdio> #include<algorithm> #include<cstring ...
- 【记忆化搜索】bzoj1079 [SCOI2008]着色方案
#include<cstring> #include<cstdio> using namespace std; #define MOD 1000000007 typedef l ...
- bzoj1079: [SCOI2008]着色方案
ci<=5直接想到的就是5维dp了...dp方程YY起来很好玩...写成记忆化搜索比较容易 #include<cstdio> #include<cstring> #inc ...
随机推荐
- Day02:基本IO操作
IO流 基本IO与OS 按照流的方向主要分为输入流和输出流. 数据流按照数据单位的不同分为字节流和字符流. 按照功能可以划分节点流和处理流. 节点流与处理流 按照流是否直接与特定的地方(如磁盘.内存. ...
- Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares)
Leetcode之广度优先搜索(BFS)专题-279. 完全平方数(Perfect Squares) BFS入门详解:Leetcode之广度优先搜索(BFS)专题-429. N叉树的层序遍历(N-ar ...
- 【DSP开发】【VS开发】YUV与RGB格式转换
[视频处理]YUV与RGB格式转换 YUV格式具有亮度信息和色彩信息分离的特点,但大多数图像处理操作都是基于RGB格式. 因此当要对图像进行后期处理显示时,需要把YUV格式转换成RGB格式. RGB与 ...
- 【转帖】SQL Server 各版本发布时间和开发代号
SQL Server 各版本发布时间和开发代号 2019年01月23日 11:07:44 努力挣钱娶媳妇的苗同学 阅读数 278 https://blog.csdn.net/weixin_446098 ...
- 修改公司VS_UCOS工程BUG调试过程说明
说明:公司里的工程中,使用VS_UCOS来调试应用程序.业务逻辑.方法是嵌入式和VS分别建一个工程,把底层驱动部分分别添加各自需要的源文件,头文件使用同一个.也就是嵌入式的驱动函数名和参数和VS的函数 ...
- Codeforces 1221F. Choose a Square
传送门 对于某个点 $(x,y)$ ,不妨设 $x<y$ 因为如果 $x>y$ 直接按 $y=x$ 对称一下即可 当且仅当正方形左下角 $(a,a)$ 满足 $a<=x$,右上角 $ ...
- [Next] 六.next的优化
导出 html 并开启服务 我们将 pages 下页面导出为静态 HTML 页面.首先,next.config.js 在应用程序的根目录中创建一个名为的文件,并添加以下内容 exportPathMap ...
- Javassist操作方法总结
CSDN参考Javassist tutorial 1.读取和输出字节码 ClassPool pool = ClassPool.getDefault(); //会从classpath中查询该类 CtCl ...
- Linux配置nginux
安装依赖 yum install gcc yum install pcre-devel yum install zlib zlib-devel yum install openssl openssl- ...
- PL/SQL题型代码示例
1.记录类型(注意标点符号的使用) 结果: 2.学习流程 3. 4. 5. 6. 写法二: 结果: 写法三: 7.使用循环语句打印1-100 方法一: 或者 方法二: 方法三: 8. 方法二: 9. ...