[微软编程之美挑战赛P2]女神---CLJ神犇的代码

Time Limit: 20000ms
Case Time Limit: 10000ms
Memory Limit: 256MB

Description

在 牧场物语 游戏中,如果第一次进入游戏就是春1日,开电视按左键就有和女神猜数字的游戏。

如果第二年春1日要玩猜拳游戏,要第一年冬30日参加过除夕大会。


地点:自家住宅


时间:每年的春之月,一到五日(新年特别节目)


游戏角色:女神


可玩次数:5次


注意手上别拿任何物品,否则无法拿取奖品。


打开电视(4个方向有不同的节目),这时候会出现由女神主持的猜数字大小节目,只要按左键频道就可换至此节目。


玩法很简单,女神说一个数字,你猜下一个数字比这个数字大还是小,数字为0-9这几个数。如果相同,继续猜,猜中的次数决定你的奖品,奖品答完后奖品直接到手上。



奖品:

0~1 没东西

2次药草 (各种颜色都有机会得到)

3~9 乔麦粉或年糕 (随机取得)

10~14 轻松茶茶叶

15~19 防晒霜

20~25 润肤霜

26~29 面膜

30~39 香水

40~49 礼物 (保装好的裙子)

50~59 黄金资材 (买价10万G,但不能卖出)

60~69 古代鱼化石 (可卖5000G)

70~79 海盗的宝藏 (可卖10000G)

80~89 料理瓶子 (番茄酱的制作方法)

90~99 料理石板 (考地瓜的制作方法)

100~oo 女神猜拳证书


比如说,一开始女神说数字5,你第一次猜"大",然后女神说数字8,8 > 5, 你说对了一次;

然后,第二次你猜"小",然后女神说数字4, 4 < 8, 你说对了第二次;

然后,第三次你猜"大",然后女神说数字4,4 = 4,女神要你重新说;

然后,第四次你猜"大",然后女神说数字7,7 > 4, 你说对了第三次;

然后,第五次你猜"小",然后女神说数字9,9 > 7, 你猜错了。

于是你总共说对了3次,获得荞麦粉.


你可以假设,每次出现0-9的概率是相同的,都为10%


由于GG不屑与使用金手指等即时存档工具(但是他会在猜数字开始前,存一个档,如果猜数字游戏的结果不理想,他会执着的反复读档重来),所以他想知道的是,假设他十分理智,请问他期望猜多少次,才能在一次游戏中,猜对≥ expect次。


注意:

这里认为的猜一次,是一次选择大小的过程,也就是说,一局游戏中,会猜很多次。而偏执的GG会反复的玩很多局游戏,直到达到目的。

这里认为,GG的足够理智体现在:

如果在一局游戏中,还没有猜正确够expect次,则他会如果上一个数字 ≥ 5,则猜小;如果上一个数字 ≤ 4,则猜大

如果在一局游戏中,他已经猜正确够expect次,则他会如果上一个数字 ≥ 5,则猜大;如果上一个数字 ≤ 4,则猜小,因为已经达到目的后,他希望这局游戏快点结束。

Input

输入首先是一个整数T ( 1 ≤ T ≤ 100 ), 表示测试数据组数

每组测试数据占一行,为一个整数expect,表示GG要在一局游戏中至少猜对expect次。

Output

如果你的答案,和正确答案的差的绝对值≤ 1,则被认为是正确的。具体格式详见样例。

Test Data

大数据:1 ≤ expect ≤ 30

小数据:1 ≤ expect ≤ 100

Hint

看起来游戏没有想象得那么困难,要想猜对10次,获得轻松茶茶叶,期望次数不是1024次,而是77.3次。当然您非要拿到证书的话,就自求多福了。。。

对于大数据,请务必小心精度问题!



Sample Input
2
10
20
Sample Output
Case 1: 77.296707046573422
Case 2: 1476.186702884801103

今天编程之美挑战赛上CLJ完虐PKU的吴铮锴等人,满分100分拿到了80分,最神奇的是他居然在比赛最后9min怒虐第3题,而且还是一遍AC,牛翻了。更有意思的是他在写第二题的时候,在程序最后几行加上了一个笑脸的注释,眼神直飘右边的网友评论栏,真是大神回眸一笑百媚生啊。。。

下面就是CLJ大神牛气哄哄的代码(虽然只过了小数据),抢在他开始虐第3题前一刻copy来的

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<vector>
#include<iostream>
#include<cmath>
#define REP(i,n) for(int i=0;i<n;++i)
using namespace std;

const int MAX_N=100+10;
const int MAX_L=1000+10;

int id[MAX_N][10];

long double equ[MAX_L][MAX_L],b[MAX_L];

void gauss(long double ans[],int n){
    int at[1001]={};
    memset(at,-1,sizeof at);
    
    bool used[1001]={};//for row
    
    REP(iter,n){
        int r,who=-1;
        REP(rr,n)if(!used[rr])REP(c,n)
            if(at[c]==-1 && 
                (who==-1||fabs(equ[rr][c])>fabs(equ[r][who])))
                    r=rr,who=c;
        
        used[r]=true;            
        long double by=equ[r][who];
        REP(c,n)
            equ[r][c]/=by; b[r]/=by;
        REP(nr,n) if(r!=nr) {
            long double by=equ[nr][who];
            REP(c,n) equ[nr][c]-=equ[r][c]*by;
            b[nr] -= b[r]*by;
        }
        at[who]=r;
    }
    REP(i,n)
        ans[i]=b[at[i]];
}

typedef long double ld;

struct Pair{
    ld a,b; //a+b*x[rt]
    Pair(ld a=0,ld b=0):a(a),b(b){}
    Pair operator+(const Pair&o)const{return Pair(a+o.a,b+o.b);}
    Pair operator-(const Pair&o)const{return Pair(a-o.a,b-o.b);}
    Pair operator*(ld o)const{return Pair(a*o,b*o);}
};

long double solve(int n){
    int nid=0;
    
    memset(equ,0,sizeof equ);
    memset(b,0,sizeof b);
    
    long double end[10];
    REP(i,10){
        equ[i][i]-=1;
        b[i]=-1;
        
        REP(j,10) {
            bool ok=false;
            if(i<=4&&j>i)
                ok=true;
            if(i>=5&&j<i)
                ok=true;
            if(ok)
                continue;
            equ[i][j]+=0.1;
        }
    }
    
    gauss(end,10);
    
    memset(equ,0,sizeof equ);
    memset(b,0,sizeof b);
    
    nid=0;
    REP(i,n) REP(j,10)
        id[i][j]=nid++;
    int rt=nid++;
    
    equ[rt][rt]-=1;
    REP(j,10){
        equ[rt][id[0][j]]+=0.1;
    }
    
    REP(i,n) REP(j,10) {
        int me=id[i][j];
        equ[me][me]-=1;
        b[me]=-1;
        REP(k,10){
            bool ok=false;
            if(j<=4 &&k>j) ok=true;
            if(j>=5 &&k<j) ok=true;
            if(k==j){
                equ[me][me]+=0.1;
                continue;
            }
            if(ok) {
                if(i+1==n){
                    b[me]-=0.1*end[k];
                    continue;
                }
                int nxt=id[i+1][k];
                equ[me][nxt]+=0.1;
            } else {
                int nxt=rt;
                equ[me][nxt]+=0.1;
            }
        }
    }
    
    long double ans[1001];
    gauss(ans,nid);
    return ans[rt];
}


long double solve2(int n){
    int nid=0;
    
    memset(equ,0,sizeof equ);
    memset(b,0,sizeof b);
    
    long double end[10];
    REP(i,10){
        equ[i][i]-=1;
        b[i]=-1;
        
        REP(j,10) {
            bool ok=false;
            if(i<=4&&j>i)
                ok=true;
            if(i>=5&&j<i)
                ok=true;
            if(ok)
                continue;
            equ[i][j]+=0.1;
        }
    }
    
    gauss(end,10);
    
    Pair what[MAX_L];
    
    nid=0;
    REP(i,n) REP(j,10)
        id[i][j]=nid++;
    int rt=nid++;
    
    for(int i=n-1;i>=0;--i) REP(j,10) {
        int me=id[i][j];
        Pair ret(1.0,0.0);
        
        REP(k,10){
            bool ok=false;
            if(j<=4 &&k>j) ok=true;
            if(j>=5 &&k<j) ok=true;
            if(k==j){
                continue;
            }
            if(ok) {
                if(i+1==n){
                    ret.a+=0.1*end[k];
                    continue;
                }
                int nxt=id[i+1][k];
                ret=ret+what[nxt]*0.1;
            } else {
                ret.b+=0.1;
            }
        }
        
        ret=ret*(1.0/0.9);
        what[me] = ret;
    }
    
    Pair at;
    REP(i,10)
        at = at + what[id[0][i]]*0.1;
    
    ld ans = at.a/(1-at.b);
    return ans;
}

//19720015116700.7968750000 : long double
//19700972735325.7460937500 :long long double
//19714311348273.06640625000000000000
// >_>

int main(){
    int T;cin>>T;
    REP(i,T) {
        int n;cin>>n;
        printf("Case %d: %0.20lf\n",i+1,(double)solve2(n));
    }
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值