[JZOJ3424] 【NOIP2013模拟】粉刷匠
题目
题目大意
有\(K\)种颜色的小球,每种颜色的小球有\(c_i\)个。
求相邻颜色不同的排列的方案数。
\(K\leq 15\)且\(c_i\leq 6\)
思考历程&正解1
我是一个智障,所以就先想到了一个智障方法。
首先考虑暴力。
暴力的时候记录上一个的颜色和每种颜色剩余的小球数量,转移的时候选择一种与上一个颜色不同的小球,将它的个数减一。
设状态\(f_{S,i}\)表示状态为\(S\),最后一个小球颜色为\(i\)的方案数。
显然直接这样设状态会爆掉吧……
接着我们发现答案是与小球的顺序无关的,那我们可以考虑将组成一样的压起来。
建立一个桶,桶的下标范围是\([0,6]\),表示小球的个数。桶中的每个元素表示的是小球的个数为下标的颜色个数。
显然,桶的每个元素加起来等于\(15\)(如果一开始\(K<15\),就补\(0\))
可以计算这个桶的方案数:
相当于将\(15\)个球放进\(7\)个箱子里,每个箱子可以为空:\(C_{15+7-1}^{7-1}=54264\)
可以存下。
这个桶可以用个\(7\)位的\(16\)进制数来存,不会超过int。用\(map\)给每个桶分配一个下标。
然后\(i\)的定义也要变一下,表示最后一个小球的颜色的个数。范围在\([0,6]\),显然不会炸。
由于多组数据,所以考虑反着转移。\(f_{S,i}\)中的\(S\)表示的状态是已经放了的状态(不是剩余的状态)。
转移的时候枚举\(j\)。设桶下标为\(j\)的数是\(k\),如果\(i=j\),由于不能重复,所以乘上\(k-1\)。否则直接乘\(k\)。
这些是预处理的部分。对于每个询问,由于它按照一定顺序排列,所以要除以排列数。排列数有个公式:\(\frac{(\sum{c_i})!}{\prod {c_i!}}\)(不会证明……)
正解2
DYP的高级解法。
设\(f_{i,j}\)表示做到第\(i\)个颜色,相邻相等的个数为\(j\)。
按照颜色一层一层转移,每次转移的时候插空。
现在由\(f_{i,j}\)往后面的转移,设\(sum=\sum_{1\leq k\leq i}{c_k}\)
枚举插空的位置个数\(x\)和插在相邻相等位置之间的个数\(y\)。
转移:\(f_{i,j}*C_{sum+1-j}^{x-y}*C_j^y\to f_{i+1,j-y+c_{i+1}-x}\)
感觉我的方法简单多了
代码(正解1)
using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>
#include <cassert>
#define mo 1000000007
inline int my_pow(int x,int y){
int res=1;
for (;y;y>>=1,x=1ll*x*x%mo)
if (y&1)
res=1ll*res*x%mo;
return res;
}
int pow16[8],fac[16];
int cnt;
map<int,int> h;
int f[200000][7];
int q[200000];
inline void init(){
h[15]=++cnt;
f[cnt][6]=1;
int head=0,tail=1;
q[1]=15;
do{
int x=q[++head],s=h[x];
for (int j=0;j<6;++j){
int k=x/pow16[j]%16;
if (k){
int y=x-pow16[j]+pow16[j+1];
int *p=&h[y];
if (*p==0){
*p=++cnt;
q[++tail]=y;
}
for (int i=1;i<=6;++i)
(f[*p][j+1]+=1ll*f[s][i]*(i!=j?k:k-1)%mo)%=mo;
}
}
}
while (head!=tail);
}
int main(){
pow16[0]=1;
for (int i=1;i<=7;++i)
pow16[i]=pow16[i-1]*16;
fac[0]=1;
for (int i=1;i<=15;++i)
fac[i]=1ll*fac[i-1]*i%mo;
init();
int T;
scanf("%d",&T);
while (T--){
int K;
scanf("%d",&K);
int x=15-K;
for (int i=1;i<=K;++i){
int c;
scanf("%d",&c);
x+=pow16[c];
}
int s=h[x];
long long ans=0;
for (int i=1;i<=6;++i)
ans+=f[s][i];
ans%=mo;
for (int i=0;i<=6;++i)
ans=1ll*ans*fac[x/pow16[i]%16]%mo;
ans=1ll*ans*my_pow(fac[15],mo-2)%mo;
printf("%lld\n",ans);
}
return 0;
}
总结
排列组合一类的DP,可以试着一层层插空。
[JZOJ3424] 【NOIP2013模拟】粉刷匠的更多相关文章
- 2014.7.8模拟赛【笨笨当粉刷匠】|bzoj1296 [SCOI]粉刷匠
笨笨太好玩了,农田荒芜了,彩奖用光了,笨笨只好到处找工作,笨笨找到了一份粉刷匠的工作.笨笨有n条木板需要被粉刷.每条木板被分成m个格子,每个格子要被刷成红色或蓝色.笨笨每次粉刷,只能选择一条木板上一段 ...
- 【JZOJ3424】粉刷匠
description 赫克托是一个魁梧的粉刷匠,而且非常喜欢思考= = 现在,神庙里有N根排列成一直线的石柱,从1到N标号,长老要求用油漆将这些石柱重新粉刷一遍.赫克托有K桶颜色各不相同的油漆,第i ...
- BZOJ 1296: [SCOI2009]粉刷匠 分组DP
1296: [SCOI2009]粉刷匠 Description windy有 N 条木板需要被粉刷. 每条木板被分为 M 个格子. 每个格子要被刷成红色或蓝色. windy每次粉刷,只能选择一条木板上 ...
- cojs 疯狂的粉刷匠 疯狂的斐波那契 题解报告
疯狂的斐波那契 学习了一些奇怪的东西之后出的题目 最外层要模p是显然的,然而内层并不能模p 那么模什么呢,显然是模斐波那契的循环节 那么我们可以一层层的求出每层的斐波那契循环节 之后在从内向外用矩阵乘 ...
- BZOJ 1296: [SCOI2009]粉刷匠( dp )
dp[ i ][ j ] = max( dp[ i - 1 ][ k ] + w[ i ][ j - k ] ) ( 0 <= k <= j ) 表示前 i 行用了 j 次粉刷的机会能正 ...
- 【NOIP2013模拟】终极武器(经典分析+二分区间)
No.2. [NOIP2013模拟]终极武器 题意: 给定你一些区间,然后让你找出\(1\sim 9\)中的等价类数字. 也就是说在任何一个区间里的任何一个数,把其中后\(k\)位中的某一位换成等价类 ...
- 【BZOJ1296】[SCOI2009]粉刷匠(动态规划)
[BZOJ1296][SCOI2009]粉刷匠(动态规划) 题面 BZOJ 洛谷 题解 一眼题吧. 对于每个串做一次\(dp\),求出这个串刷若干次次能够达到的最大值,然后背包合并所有的结果即可. # ...
- bzoj1296【SCOI2009】粉刷匠
1296: [SCOI2009]粉刷匠 Time Limit: 10 Sec Memory Limit: 162 MB Submit: 1479 Solved: 837 [id=1296" ...
- 1296: [SCOI2009]粉刷匠[多重dp]
1296: [SCOI2009]粉刷匠 Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 1919 Solved: 1099[Submit][Statu ...
- 【BZOJ1296】[SCOI2009]粉刷匠 (DP+背包)
[SCOI2009]粉刷匠 题目描述 \(windy\)有 \(N\) 条木板需要被粉刷. 每条木板被分为 \(M\) 个格子. 每个格子要被刷成红色或蓝色. \(windy\)每次粉刷,只能选择一条 ...
随机推荐
- python语言和R语言实现机器学习算法
<转>机器学习系列(9)_机器学习算法一览(附Python和R代码) 转自http://blog.csdn.net/han_xiaoyang/article/details/51191 ...
- 2019ICPC南京网络赛F Greedy Sequence
题意:对于1<=i<=n每次找到(pos[i]-k,pos[i]+k)内不大于i的最大那个数,ans[i]=ans[mx]+1,若ans[mx]未知则递归处理ans[mx] PS:这个题比 ...
- str2int HDU - 4436 后缀自动机求子串信息
题意: 给出 n 个串,求出这 n 个串所有子串代表的数字的和. 题解; 首先可以把这些串构建后缀自动机(sam.last=1就好了), 因为后缀自动机上从 root走到的任意节点都是一个子串,所有可 ...
- Java中equals和hashcode的区别?
Java中equals和hashcode方法是在Object对象中的,所以每个对象都有这两个方法,大多数时候我们为了实现特定需求需要重写这两个方法 equals和hashcode方法常用在同一个类中用 ...
- Spring BeanName生成规则
1. XML方式 <bean class="com.fishblog.service.UserService"></bean> beanName: com. ...
- 解决 php artisan route:list 报错oauth-private.key文件不存在或不可读的
进入项目根目录命令行执行 php artisan passport:install 然后执行php artisan route:list,会提示 Class App\Http\Controllers\ ...
- Vue Router基础
路由 安装 vue-router 起步 <router-link to="/foo">Go to Foo</router-link> <router- ...
- 记录一下webpack好用的node模块
postcss-loader autoprefixer: 自动添加css前缀 css-loader: 能在js文件中导入css(配合React比较好,我猜) style-loader: 将所有的计算后 ...
- delphi 安卓开发常用
delphi 安卓开发有几个常用的pas: FMX.Helpers.Android, Androidapi.JNI.Net, Androidapi.JNI.GraphicsContentViewTex ...
- NX二次开发-直线分析函数UF_EVAL_ask_line与NXOpen::Line直线分析的用法
NX11+VS2013 #include <NXOpen/Line.hxx> #include <NXOpen/NXException.hxx> #include <NX ...