首页 > 代码库 > Foreign Postcards
Foreign Postcards
题意:
给定 n 张排成一堆的的卡片,每一次从堆顶上等概率随机取出 [1~当前卡片数] 个卡片,如果堆顶的卡片是反面朝上,
则将所有取出的卡片翻转,求问期望取出多少个反面朝上的卡片。
解法:
考虑dp,首先有期望的可加性得
$ans = \sum_{i=1}^n{ P(card_i \ is \ reversed \ when \ got) }$
这样考虑求后面的概率。
用 $f(i)$ 表示以 $i$ 为取出的卡片的顶上的卡片的概率。
$f(1) = 1$
$f(i) = \sum{ \frac{f(j)}{n-j+1} }$
这样记$h(i,0), h(i,1)$ 分别表示第 $i$ 张卡片被一张正面朝上的卡消去 和 被一张反面朝上的卡消去的概率。
从而有
$$h(i,0) = \sum{1 \leq j \leq i, S(j-1) = ‘C‘}_{ f(j) \frac{n-i+1}{n-j+1} }$$
$h(i,1)$ 递推式同理。
对两个式子记一下前缀和,$O(n)$
#include <iostream> #include <cstdio> #include <cstring> #define LD double #define N 1000010 using namespace std; int n; LD f[N]; char S[N]; int main() { freopen("foreign.in", "r", stdin); freopen("foreign.out", "w", stdout); while(~scanf("%s",S)) { n = strlen(S); f[1] = 1; f[2] = 1.0 / (LD)n; for(int i = 2;i < n;i++) f[i+1] = f[i] + f[i] / (n-i+1); LD sumC = 0, sumW = 0, ans = 0; for(int i = 1;i <= n;i++) { if(S[i-1] == ‘C‘) sumC += f[i] / (n-i+1.0); else sumW += f[i] / (n-i+1.0); if(S[i-1] == ‘C‘) ans += (n-i+1.0) * sumW; else ans += (n-i+1.0) * sumC; } printf("%.10lf\n", ans); } fclose(stdin); fclose(stdout); return 0; }
Foreign Postcards
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。