zoukankan      html  css  js  c++  java
  • bzoj4318 OSU!和bzoj 3450 Tyvj1952 Easy

    这俩题太像了

    bzoj 3450 Tyvj1952 Easy

    Description

    某一天WJMZBMR在打osu~~~但是他太弱逼了,有些地方完全靠运气:(
    我们来简化一下这个游戏的规则
    有n次点击要做,成功了就是o,失败了就是x,分数是按comb计算的,连续a个comb就有aa分,comb就是极大的连续o。
    比如ooxxxxooooxxx,分数就是2
    2+4*4=4+16=20。
    Sevenkplus闲的慌就看他打了一盘,有些地方跟运气无关要么是o要么是x,有些地方o或者x各有50%的可能性,用?号来表示。
    比如oo?xx就是一个可能的输入。
    那么WJMZBMR这场osu的期望得分是多少呢?
    比如oo?xx的话,?是o的话就是oooxx => 9,是x的话就是ooxxx => 4
    期望自然就是(4+9)/2 =6.5了

    Input

    第一行一个整数n,表示点击的个数
    接下来一个字符串,每个字符都是ox?中的一个

    Output

    一行一个浮点数表示答案

    (nleq 300000)


    一开始想对每一块连续的确定的(o)来维护,但显然不行
    由于答案是长度的平方,所以可以先维护一个期望长度
    (len_i)表示以(i)结尾的期望长度
    你显然,如果当前是(o,len_i=len_{i-1}+1),当前为(x,len_i=0)
    如果是不确定,又因为概率是二分之一,那期望就是上面两种情况加起来除以二,(len_i=dfrac{len_{i-1}+1}{2})

    然后很容易观察到的是((x+1)^2=x^2+2x+1)
    所以可以由这个式子从长度推到答案
    (f_i)(1)(i)位答案的期望,这里和刚才(len)不同
    还是分三种情况讨论
    已经确定的两种情况都很简单,是(o)(f_i=f_{i-1}+2len_{i-1}+1),是(x)(f_i=f_{i-1})
    因为这里是统计的(1)(i)的期望答案,所以也要把前面的期望累加上
    如果不确定,就是(f_i)有一半的几率能加上(2len_{i-1}+1),所以(f_o=f_{i-1}+dfrac{2len_{i-1}+1}{2})

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	int x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    int n;
    char s[300006];
    double len[300006],f[300006];//len是以i结尾的期望长度 
    int main(){
    	n=read();
    	std::scanf("%s",s+1);
    	for(reg int i=1;i<=n;i++){
    		if(s[i]=='o'){
    			len[i]=len[i-1]+1;
    			f[i]=len[i-1]*2+1+f[i-1];
    		}
    		else if(s[i]=='x'){
    			len[i]=0;f[i]=f[i-1];
    		}
    		else{
    			len[i]=(len[i-1]+1)/2;
    			f[i]=(len[i-1]*2+1)/2+f[i-1];
    		}
    	}
    	std::printf("%.4lf",f[n]);
    	return 0;
    }
    

    bzoj4318 OSU!
    这个就是前面那个的升级版

    Description

    osu 是一款群众喜闻乐见的休闲软件。
    我们可以把osu的规则简化与改编成以下的样子:
    一共有n次操作,每次操作只有成功与失败之分,成功对应1,失败对应0,n次操作对应为1个长度为n的01串。在这个串中连续的 X个1可以贡献X^3 的分数,这x个1不能被其他连续的1所包含(也就是极长的一串1,具体见样例解释)
    现在给出n,以及每个操作的成功率,请你输出期望分数,输出四舍五入后保留1位小数。

    Input

    第一行有一个正整数n,表示操作个数。接下去n行每行有一个[0,1]之间的实数,表示每个操作的成功率。

    Output

    只有一个实数,表示答案。答案四舍五入后保留1位小数。

    (nleq 100000)


    还是用之前的思路,维护一个长度
    但是这次转移就是(len_i=(len_{i-1}+1)cdot p)了,因为它有(p)的概率能加一,而剩下(1-p)的几率变成0
    由于((x+1)^3=x^3+3x^2+3x+1),所以还要再维护一个长度平方的期望才能得到答案
    因为期望的平方不一定等于平方的期望,这是看了别人blog才知道的,并不会证
    长度平方的期望和刚才差不多,但并不完全一样,这只算上以(i)结尾的长度的平方
    算答案就照搬这个式子然后乘上(p)就行

    #include<cstdio>
    #include<algorithm>
    #include<iostream>
    #include<cmath>
    #include<iomanip>
    #include<cstring>
    #define reg register
    #define EN std::puts("")
    #define LL long long
    inline int read(){
    	int x=0,y=1;
    	char c=std::getchar();
    	while(c<'0'||c>'9'){if(c=='-') y=0;c=std::getchar();}
    	while(c>='0'&&c<='9'){x=x*10+(c^48);c=std::getchar();}
    	return y?x:-x;
    }
    int n;
    double f[100006],sqr[100006],len[100006];
    int main(){
    	n=read();
    	reg double p;
    	for(reg int i=1;i<=n;i++){
    		std::scanf("%lf",&p);
    		len[i]=(len[i-1]+1)*p;
    		sqr[i]=(sqr[i-1]+len[i-1]*2+1)*p;
    		f[i]=f[i-1]+(3*sqr[i-1]+3*len[i-1]+1)*p;
    	}
    //		for(reg int i=1;i<=n;i++) std::printf("%.3lf %.3lf %.3lf
    ",len[i],sqr[i],f[i]);
    	std::printf("%.1lf",f[n]);
    	return 0;
    }
    

    其实这两段代码中的数组是可以省掉的,只记录一个之前以为的信息

  • 相关阅读:
    Teradata中fastload使用
    Teradata 的rank() 和 row_number() 函数
    Oracle 10g下载链接
    SSH时不需输入密码
    Linux环境下GIT初次使用
    模块与包的概念
    迭代器 生成器
    Python
    Python
    函数式编程-尾递归、尾调用
  • 原文地址:https://www.cnblogs.com/suxxsfe/p/12533357.html
Copyright © 2011-2022 走看看