[Luogu2719] 搞笑世界杯 [概率期望]

[ L i n k \frak{Link} Link]


这题我会! C 2 n n 2 C 2 n − 2 n \frak{\dfrac{C^n_{2n}}{2C^{n}_{2n-2}}} 2C2n2nC2nn个鬼

上面做法的前提是每一种组合出现的概率完全一致。
但是这道题目它
显然不是的吧?
重点就在于,每一种的个数是有限制的
就是,可能到某个位置,就再也不用考虑某一种票:因为这种票没了。
所以要按位置递推。

有两种想法,第一种是f(i,j)表示位置i放了j个某种票,
第二种是表示某个位置放了i个某种票、j个另一种票。
我比较鶸,思维氵化了,根本没有想到第二种(


第一种

#include
#include
#include
#include
#include
using namespace std;
int n, fn;
double f[1255][648];
int main() {
	scanf("%d",&n);
	fn = n >> 1;
	f[1][0] = f[1][1] = 0.5;
	for (int i = 1; i < n; ++i) {
		for (int j = 0; j <= i; ++j) {
			int k = i - j;
			if (k > fn) continue;
			if (j > fn) continue;
			if (j == fn) {
				f[i+1][j] += f[i][j];
			}
			else if (k == fn) {
				f[i+1][j+1] += f[i][j];
			}
			else f[i+1][j+1] += f[i][j] * 0.5,
				 f[i+1][j] += f[i][j] * 0.5;
			
		}
	}
	printf("%.4f", 2 * f[n-2][fn]);
	return 0;
}

第二种
按照“有多少个A,B的时候,
假如最后一个选了A/B
倒数第二个和最后一个选的票种类相同”的概率来转移。
可能这就是大佬吧

#include
#include
#include
#include
#include
using namespace std;
int n, fn;
double f[1255][648];
int main() {
	scanf("%d",&n);
	fn = n >> 1;
	f[1][0] = f[1][1] = 0.5;
	for (int i = 1; i < n; ++i) {
		for (int j = 0; j <= i; ++j) {
			int k = i - j;
			if (k > fn) continue;
			if (j > fn) continue;
			if (j == fn) {
				f[i+1][j] += f[i][j];
			}
			else if (k == fn) {
				f[i+1][j+1] += f[i][j];
			}
			else f[i+1][j+1] += f[i][j] * 0.5,
				 f[i+1][j] += f[i][j] * 0.5;
			
		}
	}
	printf("%.4f", 2 * f[n-2][fn]);
	return 0;
}

概率真的没怎么做过也不怎么会做,被吊打了。。

你可能感兴趣的:(dp,Luogu,概率dp,概率期望)