Beating the Dataset LightOJ - 1274(期望dp)

You are in a contest, and unfortunately you don't have much time. You have one problem in hand; you just glanced at the sample output and found that it just wants 'YES' or 'NO'. So, you have made another plan instead of solving the problem as you know the system very well.

For this problem, every test case is stored in a separate file. When a submission is found, the system successively runs the solution on all tests of a problem, and for each test the checking process goes as follows. The input is copied to the file input.txt. Then the solution is launched. It reads the input from the file input.txt and writes the result to the file output.txt. When it finishes, the correct answer is copied to the file answer.txt. If the contents of the files answer.txt and output.txt match, the test is assumed to be passed; otherwise, the test is not passed.

So, you decided to write a program that would operate as follows. If the folder containing the program doesn't contain the file answer.txt (i.e. the program is run on the first test), then the program outputs "YES". Otherwise, the program outputs the contents of the file answer.txt. And before the contest, the sizes of the data files are given to you.

And it's clear that the size of the file with the answer "YES" is 3 bytes, the size of the file with the answer "NO" is 2 bytes, and all the variants of the order of tests are equally probable. Now you want to calculate the average number of tests that your solution won't pass.

Input

Input starts with an integer T (≤ 10), denoting the number of test cases.

Each case starts with a line containing two integers n (1 ≤ n ≤ 5000) and s (2n ≤ s ≤ 3n)where n denotes the number of data sets and s denotes the total size of the answer files.

Output

For each case, print the case number and the average number of tests your solution won't pass. Error less than 10-6 will be ignored.

Sample Input

4

3 7

1 2

1 3

4 10

Sample Output

Case 1: 2

Case 2: 1

Case 3: 0

Case 4: 2.5000000000

Note

For the first case, one of the three answers is "YES" and two answers are "NO". If the order of tests is "YES-NO-NO", then your solution won't pass the second test only; if the order is "NO-YES-NO", then it will pass none of the tests; if the order is "NO-NO-YES", the solution won't pass the first and the third tests.

思路:第一行一定是输入yes,而后面的输入内容取决于上一步的正确答案,也就是说,如果按顺序推的话,下一步的出现yes或no的概率是一个定值,无法计算期望。

反过来想,其实第i+1个输入yes或者是no的概率,其实是第i个出现正确答案是yes还是no的概率,所以逆推可以解决这个问题。

分析期望与哪几项有关可以帮助分析出状态,首先yes的剩余个数决定着下一步出现yes的概率,其次第i步出现yes或者no决定着第i+1步的成功与失败,

总结下来,dp[i][j][k]表示第i行,前i行用掉的yes个数,且第i行为yes或者no的概率。用0代表yes。

dp[i][j][0]=dp[i+1][j+1][0]*p(yes出现概率)+(dp[i+1][j][1]+1)*p(no出现概率)

同理dp[i][j][1]......

代码:

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<iostream>
#include<map>
#include<string>
#include<cstring>
#include<vector>
#include<algorithm>
#include<set>
#include<sstream>
#include<cstdio>
#include<cmath>
#include<climits>
using namespace std;
const int maxn=5e3+9;
double dp[2][maxn][2];
int main(int argc, char const *argv[])
{
    #ifndef ONLINE_JUDGE
        freopen("in.txt","r",stdin);
        freopen("out.txt","w",stdout);
    #endif
    int T;
    int cas=0;
    cin>>T;
    while(T--)
    {
        int n,s;
        scanf("%d%d",&n,&s);
        int yes=s-2*n;
        int no=n-yes;
        memset(dp,0,sizeof(dp));
        for(int i=n-1;i>=0;i--)
        {
            int ret=n-i,now=(i)%2,nxt=(i+1)%2;
            int Max=min(i,yes),Min=max(0,i-no);
            memset (dp[now], 0, sizeof (dp[now]));
            for (int j = Min; j <= Max; j++) 
            {
                double p1 = 1.0 * (yes - j) / ret, p2 = 1.0 * (no - (i - j)) / ret;
                dp[now][j][0] = dp[nxt][j + 1][0] * p1 + (dp[nxt][j][1] + 1) * p2;
                dp[now][j][1] = (dp[nxt][j + 1][0] + 1) * p1 +  dp[nxt][j][1] * p2;
            }
        }
        printf ("Case %d: %.7f\n", ++cas, dp[0][0][0]);//第一行只能输出YES
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值