【刷题】清橙 A1295 necklace
试题来源
清华大学2011年百名信息学优秀高中学子夏令营
问题描述
有人打算送给你一条宝石项链,包含了N颗五颜六色(一共有M种颜色)的宝石。因为本问题中你只关心每个宝石的颜色,而且项链现在两头还没有接在一起,它可以被看成是一个数字串。
你希望在五颜六色的宝石中看到连续的一段同色宝石。因此,你定义一根宝石项链的幸运度是它最长的由同色宝石构成的连续子串的长度。 比如,项链112322211的幸运度是3,因为它包括了由同色宝石构成的子串222。而首尾的两个11并不构成连续1111,因为这个项链现在是串形的而不是环形的。
然而,你还没有见到这个项链。你只知道每个宝石是每种颜色的概率。并且,已知每个宝石的颜色分布是独立的。现在你希望在真的见到这条项链之前计算一下,这条项链的幸运度的期望是多少?
输入格式
输入的第一行有两个正整数N和M。
后面N行每行有M个非负实数。其中第i行第j列的数P_(i,j)含义是第i个宝石是颜色j的概率是P_(i,j)。每行的M个实数保证和为1。
输出格式
一个实数,即这条项链的幸运度的期望。四舍五入至小数点后6位。
样例输入
4 2
1.0 0.0
0.5 0.5
0.0 1.0
0.5 0.5
样例输出
2.250000
样例说明
我们用1和2来分别表示两种颜色的宝石,则这串项链有四种等概率的情形:1121,1122,1221和1222。它们的幸运度分别是2,2,2,3,因此期望的幸运度是2.25。
数据规模和约定
30%的数据满足N≤16,M≤3。
60%的数据满足N≤100。
100%的数据满足2≤N≤1000,2≤M≤10。
题解
首先,先想到60分的dp,设 \(f[i][j][k][t]\) 代表到第 \(i\) 位,最长连续段长为 \(j\) ,末尾连续段长为 \(k\) ,末尾一位颜色为 \(t\) 的概率,然后暴力转移
这是60分程序:
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=100+10,MAXM=10+10;
int n,m;
db ans,f[MAXN][MAXN][MAXN][MAXM],P[MAXN][MAXM];
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
read(n);read(m);
for(register int i=1;i<=n;++i)
for(register int j=1;j<=m;++j)scanf("%lf",&P[i][j]);
for(register int i=1;i<=m;++i)f[0][0][0][i]=1.0;
for(register int i=0;i<n;++i)
for(register int j=0;j<=i;++j)
for(register int k=0;k<=j;++k)
for(register int t=1;t<=m;++t)
{
if(k<j)f[i+1][j][k+1][t]+=f[i][j][k][t]*P[i+1][t];
else f[i+1][j+1][k+1][t]+=f[i][j][k][t]*P[i+1][t];
for(register int p=1;p<=m;++p)
if(t==p)continue;
else f[i+1][j][1][p]+=f[i][j][k][t]*P[i+1][p];
}
for(register int i=1;i<=n;++i)
for(register int j=1;j<=i;++j)
for(register int k=1;k<=m;++k)ans+=f[n][i][j][k]*i;
printf("%.6f\n",ans);
return 0;
}
然后,压一维,不计某位连续段长,而在转移的时候把新的连续段长超过 \(j\) 的概率减去,保证已经考虑的位置中的连续段一定不大于 \(j\)
设 \(f[i][j][k]\) 表示到第 \(i\) 位,连续段长不超过 \(j\) ,末尾颜色为 \(k\) 的概率,\(g[i][j][k]\) 表示从第 \(i\) 位到第 \(j\) 位,期间颜色全部是 \(k\) 的概率,\(s[i][j]\) 为到第 \(i\) 位,连续段长不超过 \(j\)的概率
那么
\(s[i][j]=\sum_{k=1}^mf[i][j][k]\) ,这个很好理解
\(f[i][j][k]=s[i-1][j]*g[i][i][k]-(s[i-j-1][j]-f[i-j-1][j][k])*g[i-j][i][k]\)
这个东西有点杂
首先如果不去保证连续段长度一定不大于 \(j\) ,概率就是 \(s[i-1][j]*g[i][i][j]\) ,这个东西肯定是要减去不合法情况的,唯一的不合法情况就是加了这个新的数,使得末尾的连续段长度变成了 \(j+1\) ,也就是 \(i-j\) 到 \(i\) 期间全部都是 \(k\) 颜色。所以就是后面减去的东西。\(s[i-j-1][j]\) 减去 \(f[i-j-1][j][k]\) 是因为要保证 \(i-j-1\) 位上不能是 \(k\) 颜色,因为如果是 \(k\) 颜色,那么末尾连续段的长度就不止 \(j+1\) 了,这样的情况在之前转移的时候已经减过了
AC程序:
#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=1000+10,MAXM=10+10;
int n,m;
db ans,f[MAXN][MAXN][MAXM],P[MAXN][MAXM],g[MAXN][MAXN][MAXM],s[MAXN][MAXN];
template<typename T> inline void read(T &x)
{
T data=0,w=1;
char ch=0;
while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
if(ch=='-')w=-1,ch=getchar();
while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar();
x=data*w;
}
template<typename T> inline void write(T x,char ch='\0')
{
if(x<0)putchar('-'),x=-x;
if(x>9)write(x/10);
putchar(x%10+'0');
if(ch!='\0')putchar(ch);
}
template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);}
template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);}
template<typename T> inline T min(T x,T y){return x<y?x:y;}
template<typename T> inline T max(T x,T y){return x>y?x:y;}
int main()
{
read(n);read(m);
for(register int i=1;i<=n;++i)
for(register int j=1;j<=m;++j)scanf("%lf",&P[i][j]);
for(register int k=1;k<=m;++k)
for(register int i=1;i<=n;++i)
{
g[i][i][k]=P[i][k];
for(register int j=i+1;j<=n;++j)g[i][j][k]=g[i][j-1][k]*P[j][k];
}
for(register int i=1;i<=n;++i)s[0][i]=1;
for(register int i=1;i<=n;++i)
for(register int j=1;j<=n;++j)
for(register int k=1;k<=m;++k)
{
f[i][j][k]=s[i-1][j]*g[i][i][k];
if(i-j-1>=0)f[i][j][k]-=(s[i-j-1][j]-f[i-j-1][j][k])*g[i-j][i][k];
s[i][j]+=f[i][j][k];
}
for(register int i=1;i<=n;++i)ans+=(s[n][i]-s[n][i-1])*i;
printf("%.6f\n",ans);
return 0;
}
【刷题】清橙 A1295 necklace的更多相关文章
- 清橙A1206.小Z的袜子 && CF 86D(莫队两题)
清橙A1206.小Z的袜子 && CF 86D(莫队两题) 在网上看了一些别人写的关于莫队算法的介绍,我认为,莫队与其说是一种算法,不如说是一种思想,他通过先分块再排序来优化离线查询问 ...
- BZOJ4590 自动刷题机
Description 曾经发明了信号增幅仪的发明家SHTSC又公开了他的新发明:自动刷题机--一种可以自动AC题目的神秘装置.自动 刷题机刷题的方式非常简单:首先会瞬间得出题目的正确做法,然后开始写 ...
- 教你用python写:HDU刷题神器
声明:本文以学习为目的,请不要影响他人正常判题 HDU刷题神器,早已被前辈们做出来了,不过没有见过用python写的.大一的时候见识了学长写这个,当时还是一脸懵逼,只知道这玩意儿好屌-.时隔一年,决定 ...
- 清橙A1212:剪枝
题面 清橙 Sol 一种新的树上\(DP\)姿势 从左往右按链\(DP\) 做法: 维护两个栈\(S1\),\(S2\) \(S1\)存当前的链 \(S2\)存分叉点以下要改的链 \(Dfs\),弄一 ...
- 清橙A1202&Bzoj2201:彩色圆环
因为Bzoj是权限题,所以可以去清橙做一下 Sol 突然考了一道这样的题,考场上强行\(yy\)出来了 win下评测Long double爆零TAT 首先肯定是破环为链变成序列问题辣 那么就要求第一个 ...
- LeetCode刷题专栏第一篇--思维导图&时间安排
昨天是元宵节,过完元宵节相当于这个年正式过完了.不知道大家有没有投入继续投入紧张的学习工作中.年前我想开一个Leetcode刷题专栏,于是发了一个投票想了解大家的需求征集意见.投票于2019年2月1日 ...
- [清橙A1210]光棱坦克
[清橙A1210]光棱坦克 题目大意: 平面上放置了\(n(n\le7000)\)个反射装置,光纤将从某个装置出发,在经过一处装置时发生反射,若经过的装置坐标依次为\((x_1,y_1),(x_2,y ...
- JS、JAVA刷题和C刷题的一个很重要的区别
就是最近在做树方面的题时,发现JS和JAVA刷题和C刷题的一个很重要的区别就是传入null的区别 当遍历的时候,C传参数时可以传进去null的指针,因为递归进去,出来时,指针还是指着那个地方 但是JS ...
- lintcode 刷题 by python 总结(1)
博主之前在学习 python 的数据结构与算法的基础知识,用的是<problem-solving-with-algorithms-and-data-structure-using-python& ...
随机推荐
- Error running 'Tomcat 7': Unable to open debugger port (127.0.0.1:9342)
这个只需要把java虚拟机进程结束掉就行了
- hive 日志
hive中日志分为两种: 1 系统日志,记录hive运行情况,错误状态 2 job日志 , 记录hive中 job执行的历史过程 系统日志存储位置: 配置在 hive/conf/hive-log4j. ...
- XAF-属性编辑器中的EditMask,DisplayFormat格式化字符串该如何设置
XAF项目中有个DisplayFormat和EditMask设置,其中: 任何地方看到的DisplayFormat都是用于显示时,即非修改状态的编辑器,显示值的格式. EditMask是指编辑时的格式 ...
- The filename 未命名.ipa in the package contains an invalid character(s). The valid characters are: A-Z, a-z, 0-9, dash, period, underscore, but the name cannot start with a dash, period, or underscore
The filename 未命名.ipa in the package contains an invalid character(s). The valid characters are: A-Z ...
- MVC捕获数据保存时的具体字段验证错误代码
////捕获验证错误代码 //try //{ // // 调试写数据库 //} //catch (DbEntityValidationException dbEx) //{ //}
- Springboot 配置实现定时任务
善于思考,拥抱变化,才能拥有未来 在springboot项目中可以通过配置文件来实现定时任务的轮询,当然也可以将具体执行的corn表达式配置到数据库,实现动态从数据库获取. @Configuratio ...
- 用Python实现检测视频真伪?
译者注:本文以一段自打24小时耳光的视频为例子,介绍了如何利用均值哈希算法来检查重复视频帧.以下是译文. 有人在网上上传了一段视频,他打了自己24个小时的耳光.他真的这么做了吗?看都不用看,肯定没有! ...
- MapReduce和yarn
1.Mapreduce是什么? Mapreduce是一个分布式运算程序的编程框架,是用户开发“基于hadoop的数据分析应用”的核心框架: Mapreduce核心功能是将用户编写的业务逻辑代码和自带默 ...
- python数据可视化——matplotlib 用户手册入门:使用指南
参考matplotlib官方指南: https://matplotlib.org/tutorials/introductory/usage.html#sphx-glr-tutorials-introd ...
- selenium--判断元素是否存在
# coding:utf-8from selenium import webdriverfrom selenium.webdriver.support.ui import WebDriverWaitf ...