LightOJ 1050

由于一直感觉CSDN审查的时间真的有点让我没有办法接受,因此放弃了这个blog一段时间,但是后来的话各种博客也有着各种的不方便,自己开个主页的话又耗费精力。因此又灰溜溜的滚回来了Q+Q,然而期间的blog会慢慢回流CSDN,总之每天生活都还是要继续的~。


近况的话依然还是一样,早晨高代~下午优化,晚上coding~每天都蛮充实的,但是看着别人开始看paper我也会稍微有一点点着急。不过一切按着自己的步调来就好了不是么XD。

然后今天的题是1050(喂 怎么一个月不见才涨了10题Q+Q   原因的话大概是我比较贪玩的去了CJ然后回来的时候感冒了一趟在宿舍偷闲了几天,最终还是扛不住负罪感回实验室了2333 ,不过既然重新开始写博客就是投入正轨了嘛~!  而且之前高代感觉灵性全无~但是偷闲回来之后似乎又找到了上帝把着手推公式的感觉了XD如果能继续下去的话真的非常高兴。)




1050 - Marbles
Time Limit: 2 second(s)Memory Limit: 32 MB

Your friend Jim has challenged you to a game. He has a bag containing red and blue marbles. There will be an odd number of marbles in the bag, and you go first. On your turn, you reach into the bag and remove a random marble from the bag; each marble may be selected with equal probability. After your turn is over, Jim will reach into the bag and remove a blue marble; if there is no blue marble for Jim to remove, then he wins. If the final marble removed from the bag is blue (by you or Jim), you will win. Otherwise, Jim wins.

Given the number of red and blue marbles in the bag, determine the probability that you win the game.

Input

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

Each case begins with two integers R and B denoting the number of red and blue marbles respectively. You can assume that 0 ≤ R, B ≤ 500 and R+B is odd.

Output

For each case of input you have to print the case number and your winning probability. Errors less than 10-6 will be ignored.

Sample Input

Output for Sample Input

5

1 2

2 3

2 5

11 6

4 11

Case 1: 0.3333333333

Case 2: 0.13333333

Case 3: 0.2285714286

Case 4: 0

Case 5: 0.1218337218

 


SPECIAL THANKS: JANE ALAM JAN (DESCRIPTION, SOLUTION, DATASET)

题意的话大概就是:给你R个红球B个蓝球,R+B为奇数。你和你的对手轮流拿球,你先拿,你每次随机的拿出一个球,而你的对手每次都会拿出蓝球,问你最后一次取球取到蓝球的概率是多少?


嘤~  我可以说我组合数学并不好么?然后我就用暴力dp开始搞了Q+Q。最一开始的想法是f[i][j]表示的是对于每一个R、B而言前i次取球取出j个红球的可能性。因此这样的话方程就是显而易见的:

  1.  f [i + 1 ] [j + 1 ] + = double (f [i ] [j ] * (nr -j ) ) / double (nr +nb - 2 *i ) ;
  2.  f [i + 1 ] [j ] + = double (f [i ] [j ] * (nb - 2 *i +j ) ) / double (nr +nb - 2 *i ) ;
然而这导致的结果也非常显然,复杂度变为T*R*B 在极限数据的情况下约有2.5*1e10,这个数量级的double类型运算是很难再2秒之内得出结果的。然后就想着换个思路,要不然就直接看看能不能R*B出解的思路。于是将模型进行更改:f[i][j]表示 当红球有i个,蓝球有j个时,最后一个取到蓝球的概率。其实仅仅是换一个角度吧,递推的过程只要稍加思考就可以知道

对于f[i][j]可以转移到的只有f[i-1][j-1]或者f[i][j-2] 而如果这两个概率都可以知道的话就可以直接通过分类的加法原理分为f[i-1][j-1]与f[i][j-2],与分步的乘法原理f[i][j]--->(f[i-1][j-1] --->...--->f[0][1]  以及  f[i][j]--->(f[i][j-2]--->...--->f[0][1]) 得到,因此转移方程也是显而易见的,我就直接将其和代码一起放出:

#include<iostream>
#include<string>
#include<cstdio>
#include<cstring>
using namespace std;
double f[505][505];
bool vised[505][505];
void init(){
	memset(f,0,sizeof(f));
	memset(vised,0,sizeof(vised));
	f[0][1]=1.0,vised[0][1]=true;
	f[1][0]=0.0;vised[1][0]=true;
	for (int sep=3;sep<=1000;sep+=2)
		for (int bln=0;bln<=sep;bln++){
			int ren=sep-bln;
			if (ren>500 || ren<0 || bln>500 || bln<0)
				continue;
			double pib=double(bln*1.0)/double(bln+ren*1.0);
			double pir=double(ren*1.0)/double(bln+ren*1.0);
			if (ren-1>=0 && bln-1>=0)
				f[ren][bln]+=(pir*f[ren-1][bln-1]);
			if (ren>=0 && bln-2>=0)
				f[ren][bln]+=(pib*f[ren][bln-2]);
		}
	//printf("%lf %lf %lf %lf\n",f[1][2],f[2][3],f[2][5],f[4][11]);
}
int main(){
	init();
	int t;
	scanf("%d",&t);
	for (int cas=1;cas<=t;cas++){
		int li,ri;
		scanf("%d%d",&li,&ri);
		printf("Case %d: %.8lf\n",cas,f[li][ri]);
	}
}


 
  
好的~  今天就到此为止吧XD,最近高代不卡了~然而优化书的进度感觉稍卡,卡的原因是,书里的变量设置太多了感觉有点混乱,虽然思路可以理清但是似乎并没有掌握到本质的内容,因此我个人的想法是就先卡着2天,再斟酌一下会比较好XD。以上~!




SPECIAL THANKS: JANE ALAM JAN (DESCRIPTION, SOLUTION, DATASET)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值