HDUOJ 4649 2013多校第五场第7题

传送门

题意:给你n+1个数,n个运算符(代表在n+1个数之间的运算关系),n个概率(代表第i部运算被略去的概率),求最后期望。

吐槽:擦!大板刷题,今天下午却卡到最后都没想出来,蛋疼死的节奏。

之后看官方报告才恍然大悟,居然是二进制记录概率,哎,只怪思路不够开阔啊,赛后写了下A了。

官方思路:

G. Professor Tian

 

反状态压缩——把数据转换成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<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
using namespace std;
double a[30],d[300],ans;
int b[20],s[300],n;
char f[300],c[5];
int ca;
int main()
{
    ca=0;
    while(scanf("%d",&n)!=EOF)
    {
        for(int i=0;i<=n;i++)scanf("%d",&s[i]);
        for(int i=1;i<=n;i++)
        {
            scanf("%s",&c);
            f[i]=c[0];
        }
        for(int i=1;i<=n;i++)scanf("%lf",&d[i]);
        for(int i=1;i<=20;i++)
        {
            if(s[0]%2==1)a[i]=1;
            else a[i]=0;
            s[0]/=2;
        }
        for(int j=1;j<=n;j++)
        {
            if(f[j]=='&')
            {
                for(int i=1;i<=20;i++)
                {
                    if(s[j]%2==1)a[i]=a[i]*(1.0-d[j])+a[i]*d[j];
                    else a[i]*=d[j];
                    s[j]/=2;
                }
            }
            else if(f[j]=='|')
            {
                for(int i=1;i<=20;i++)
                {
                    if(s[j]%2==1)a[i]=(1.0-d[j])+a[i]*d[j];
                    s[j]/=2;
                }
            }
            else if(f[j]=='^')
            {
                for(int i=1;i<=20;i++)
                {
                    if(s[j]%2==1)a[i]=(1.0-a[i])*(1.0-d[j])+a[i]*d[j];
                    s[j]/=2;
                }
            }
        }
        ans=0;
        for(int i=1;i<=20;i++)
        {
            ans+=a[i]*((double)pow(2,i-1));
        }
        printf("Case %d:\n%.6f\n",++ca,ans);
    }
    return 0;
}


你可能感兴趣的:(二进制,期望,多校,Baoge)