这题起初没读懂题意,悲剧啊,然后看了题解写完就AC了

题意是给一个N,然后给N+1个整数 接着给N个操作符(只有三种操作  即  或 ,与 ,和异或 |   &  ^ )这样依次把操作符插入整数之间就可以得到一个表达式

接着给出 N 给浮点数(在0~1之间表示概率 )表示的是 操作符和他右边的整数丢失的概率。 例如下面这组数据

1

1 2

&

0.5

整数与操作符间可以组成一个表达式即 1&2 但是由于某些原因表达式的操作符和他操作的右边的

那个数有一定的概率会丢失这组数据就是 &2有 0.5的概率会丢失 ,要你算这个表达式的期望值是

多少 这组数据可以这样算 当&2不丢失的时候1&2=0

当他丢失的时候表达式就变成了1 这样这个表达式的期望值就是 0*0.5+1*0.5=0.5 ;

貌似没思路啊。。。。

思路如下:

先反状态压缩——把数据转换成20位的01来进行运算因为只有20位,而且&,|,^都不会进位,那么一位一位地看,每一位不是0就是1,这样求出每一位是1的概率,再乘以该位的十进制数,累加,就得到了总体的期望。对于每一位,状态转移方程如下:

f[i][j]表示该位取前i个数,运算得到j(0或1)的概率是多少。

f[i][1]=f[i-1][1]*p[i]+根据不同运算符和第i位的值运算得到1的概率。

f[i][0]同理。

初始状态:f[0][0~1]=0或1(根据第一个数的该位来设置)

每一位为1的期望 f[n][1]

最后的结果就是把每一位为一的概率乘上这位的位权相加就可以了

下面是我的代码:

#include<cstdio>
#include<bitset>
#include<iostream>
using namespace std;
bitset<20> team[205];//强烈推荐用bitset,这个比较快而且简单好用,关键还省空间
char ch[205];
int pow[20],n,cas=0;
double p[205], dp[20][205][2];
int cal(int i,char c,int j,int f=0)//f=0表示 默认是计算通过运算为0的概率,f=1则是去计算为1的概率
{//这个函数计算的运算结果概率只能是1或0,所以可以返回真假值
int ans;
if(c=='&') ans=i&j;
if(c=='^') ans=i^j;
if(c=='|') ans=i|j;
if(!f) return ans==0;//返回通过计算为0的概率
else return ans==1;//返回通过计算1的概率
}
int read()
{
if(!(cin>>n)) return 0;//没有读入了就返回假值
for(int a,i=0;i<=n;i++)
{
cin>>a;
team[i]=a;//用bitset转化为二进制
}
for(int i=0;i<n;i++)
cin>>ch[i];//读操作符
for(int i=0;i<n;i++)
cin>>p[i];//读概率
return 1;
}
void deal()
{
double ans=0;
for(int i=0;i<20;i++)//初始化第一位的概率
if(team[0][i]) dp[i][0][1]=1,dp[i][0][0]=0;
else dp[i][0][1]=0,dp[i][0][0]=1; for(int i=0;i<19;i++)
for(int j=1;j<=n;j++)
{
dp[i][j][1]=dp[i][j-1][1]*p[j-1]+(1-p[j-1])*(dp[i][j-1][0]*cal(0,ch[j-1],team[j][i],1)+dp[i][j-1][1]*cal(1,ch[j-1],team[j][i],1));//这个dp式如果还不懂就看一下,文章尾部我的说明。。
//计算当前为1的概率
dp[i][j][0]=dp[i][j-1][0]*p[j-1]+(1-p[j-1])*(dp[i][j-1][0]*cal(0,ch[j-1],team[j][i])+dp[i][j-1][1]*cal(1,ch[j-1],team[j][i]));
//计算当前为0的概率 和为1的概率是一回事的
} for(int i=0;i<20;i++)
ans+=pow[i]*dp[i][n][1];//统计结果
printf("Case %d:\n",++cas);
printf("%.6lf\n",ans);
}
int main()
{
for(int i=pow[0]=1;i<20;i++)
pow[i]=pow[i-1]*2;//计算二进制的位权
while(read()) deal();
return 0;
}

dp[i][j][1]=dp[i][j-1][1]*p[j-1]+(1-p[j-1])*(dp[i][j-1][0]*cal(0,ch[j-1],team[j][i],1)+dp[i][j-1][1]*cal(1,ch[j-1],team[j][i],1));

其中dp[i][j][1]表示前j个操作后使第i位变成1的概率,dp[i][j-1][1]*p[j-1],表示当前的操作符和其右边的数消失后,使这位为1的概率

(1-p[j-1])*(dp[i][j-1][0]*cal(0,ch[j-1],team[j][i],1)+dp[i][j-1][1]*cal(1,ch[j-1],team[j][i],1));这整串是在算当前的操作符和其右边的数不消失的概率,所以有公因子(1-p[j-1])即表示,表达式不消失的概率,dp[i][j-1][0]*cal(0,ch[j-1],team[j][i],1)这句是在算如果上一步当前这位计算的结果是0,那么通过这步运算得到1的概率 ,dp[i][j-1][0] 这是上一步算出这位结果为0的概率,cal(0,ch[j-1],team[j][i],1)这是算0和当前的操作符及其右边的数进行运算为1的概率,这个概率要么是一要么是0,dp[i][j-1][1]*cal(1,ch[j-1],team[j][i],1)这句就是算若上次运算的结果是1那么和当前这一步运算后得到的是1的概率,终于说完这个恶心的式子了。。。下面那个算0的式子就可以对应的去理解了,即dp[i][j][0]=dp[i][j-1][0]*p[j-1]+(1-p[j-1])*(dp[i][j-1][0]*cal(0,ch[j-1],team[j][i])+dp[i][j-1][1]*cal(1,ch[j-1],team[j][i]));

hdu 4649 Professor Tian 多校联合训练的题的更多相关文章

  1. HDU 4649 Professor Tian

    Professor Tian Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others) T ...

  2. HDU 4649 Professor Tian (概率DP)

    Professor Tian Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65535/32768 K (Java/Others)To ...

  3. HDU 5371 (2015多校联合训练赛第七场1003)Hotaru&#39;s problem(manacher+二分/枚举)

    pid=5371">HDU 5371 题意: 定义一个序列为N序列:这个序列按分作三部分,第一部分与第三部分同样,第一部分与第二部分对称. 如今给你一个长为n(n<10^5)的序 ...

  4. HDU 4649 Professor Tian(DP)

    题目链接 暴力水过的,比赛的时候T了两次,优化一下初始化,终于水过了. #include <cstdio> #include <cstring> #include <st ...

  5. hdu 4649 Professor Tian 反状态压缩+概率DP

    思路:反状态压缩——把数据转换成20位的01来进行运算 因为只有20位,而且&,|,^都不会进位,那么一位一位地看,每一位不是0就是1,这样求出每一位是1的概率,再乘以该位的十进制数,累加,就 ...

  6. HDU 4643 GSM 暑期多校联合训练第五场 1001

    点击打开链接 我就不说官方题解有多坑了 V图那么高端的玩意儿 被精度坑粗翔了 AC前 AC后 简直不敢相信 只能怪自己没注意题目For the distance d1 and d2, if fabs( ...

  7. HDU 4649 Professor Tian(反状态压缩dp,概率)

    本文出自   http://blog.csdn.net/shuangde800 题目链接:点击打开链接 题目大意 初始有一个数字A0, 然后给出A1,A2..An共n个数字,这n个数字每个数字分别有一 ...

  8. HDU 4649 - Professor Tian(2013MUTC5-1007)(概率)

    不知道这题算作什么类型的题目,反正很巧妙,队友小杰想了没一会就搞定了 为了学习这种方法,我也搞了搞,其实思路不难想,位运算嘛,只有0和1,而且该位的运算只影响该位,最多20位,一位一位地计算即可,只需 ...

  9. HDU 4649 Professor Tian(概率DP)题解

    题意:一个表达式,n + 1个数,n个操作,每个操作Oi和数Ai+1对应,给出每个操作Oi和数Ai+1消失的概率,给出最后表达式值得期望.只有| , ^,&三个位操作 思路:显然位操作只对当前 ...

随机推荐

  1. win环境下mysql5.6.14的所有变量的默认值

    在windows mysql5.6.14 x64版本下my.ini如下: [mysqld] port  = 3306 socket  = /tmp/mysql.sock basedir=D:/wamp ...

  2. IT技术如何转向销售创业

    广州 IT 网友  14:14:10 本人本科软件工程毕业,现在在一家公司做开发(不是很技术的那种),工作接近两年感觉自 己不适合这个行业,想换销售行业,不愿意在做技术.打算从事本行业的销售,老师给点 ...

  3. Merlin 的魔力: SpringLayout 管理器

    摘自http://tech.it168.com/a2009/0211/265/000000265087_all.shtml 摘自http://cache.baiducontent.com/c?m=9f ...

  4. 2D丛林逃生

    游戏介绍: 游戏地图采用二维数组:     每一个小块(Piece)类         上面有一个类型(StuffType)用于判断该小块上面站着的是什么 怪物,玩家,血瓶等等     怪物AI:   ...

  5. freemarker书写select组件错误摘要(七)

    1.错误叙述性说明 六月 26, 2014 11:26:27 下午 freemarker.log.JDK14LoggerFactory$JDK14Logger error 严重: Template p ...

  6. Dalvik虚拟机JNI方法的注册过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/8923483 在前面一文中,我们分析了Dalvi ...

  7. Android项目svn代码管理问题

    用svn控制版本,svn本身是不会识别哪些该传,哪些不该传,这就导致有些关于路径的东西(比如拓展jar的路径)也被上传了,而当别人下载后,那个路径对于这个人可能完全不存在,项目编译就会出问题.用ecl ...

  8. spring aop获取目标对象的方法对象(包括方法上的注解)

    这两天在学习权限控制模块.以前看过传智播客黎活明老师的巴巴运动网视频教程,里面就讲到权限控制的解决方案,当时也只是看看视频,没有动手实践,虽说看过几遍,可是对于系统中的权限控制还是很迷茫,所以借着这次 ...

  9. Android编译过程详解(三)

    前面两节讲解了自定义Android编译项和创建Product产品配置文件,除了编译和定义产品相关环境变量外,还需要定义Board相关环境变量. 1. build/core/config.mk 109 ...

  10. 使用 ETag 和 Last-Modified 报头减轻服务器压力(转)

    介绍你的网站在并发访问很大并且无法承受压力的情况下,你会选择如何优化?很多人首先会想从服务器缓存方面着手 对程序进行优化,许多不同的服务器缓存方式都有他们自己的特点,像我曾经参与的一些项目中,根据缓存 ...