概率、期望
前言
被dalao们虐成渣了 QAQQQQQQQ
回到正题,从高中开始,个人就挺怕概率/期望类的题目的,以为到大学可以逃过一劫,没想到竞!赛!要!考!
是福不是祸,是祸躲不过,只能好好练题找找感觉了_(:з」∠)_
A Dangerous Maze - LightOJ 1027
题意
在一个迷宫中,有n扇门,每扇门需要花费Ti时间带你出迷宫或者回到起点,求出迷宫的时间的期望值
思路
!
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
using namespace std;
int main(){
int t, csn = 1;
scanf("%d", &t);
while(t--){
int n;
int sum = 0, cnt = 0;
scanf("%d", &n);
for(int i = 0; i < n; i++){
int val;
scanf("%d", &val);
if(val < 0) cnt++;
sum += (int)fabs(val);
}
printf("Case %d: ", csn++);
if(n == cnt){
printf("inf\n");
}else{
int m = __gcd(n - cnt, sum);
printf("%d/%d\n", sum/m, (n - cnt)/m);
}
}
}
Birthday Paradox - LightOJ 1104
题意
给定n天,问要使得n天中至少有2人生日在同一天的概率不低于0.5,至少要有多少人
思路
具体查百度百科“生日悖论”
#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
int main(){
int t, csn = 1;
scanf("%d", &t);
while(t--){
int val;
scanf("%d", &val);
int ans = 1;
double sum = 1;
while(true){
sum = sum*(val - ans + 1)/val;
if(1 - sum >= 0.5) break;
ans++;
}
printf("Case %d: %d\n", csn++, ans - 1);
}
return 0;
}
Just another Robbery - LightOJ 1079
题意
哈利波特拍完戏没事做要去抢银行(出题人你这样出题会被打死的),给定危险率临界值P和m家银行,每家银行能抢劫得到的金额Mi和危险率pi,问最多能抢到多少钱
思路
一开始有想到01背包的,然而很纳闷这概率是double型的怎么做背包DP呢
翻了一下题解惊到了
把金额作为背包容量,DP安全率(1-pi),维护最大值,最后倒回来扫在安全率临界值(1-P)之上的最大金额
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1e4 + 15;
double pp[N];
int val[N];
double dp[N];
int main(){
int t, csn = 1;
scanf("%d", &t);
while(t--){
memset(dp, 0, sizeof(dp));
dp[0] = 1;
double p;
int m;
scanf("%lf%d", &p, &m);
p = 1 - p;
for(int i = 1; i <= m; i++){
scanf("%d%lf", &val[i], &pp[i]);
pp[i] = 1 - pp[i];
}
for(int i = 1; i <= m; i++){
for(int j = N - 1; j >= val[i]; j--){
dp[j] = max(dp[j], dp[j - val[i]]*pp[i]);
}
}
int ans;
for(int i = N - 1; i >= 0; i--){
if(dp[i] >= p){
ans = i;
break;
}
}
printf("Case %d: %d\n", csn++, ans);
}
return 0;
}
Race to 1 Again - LightOJ 1038
题意
一个数可以随机地从它的因子中选择一个,变成那个数,再重复以上操作,求期望步数
思路
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
using namespace std;
const int N = 1e5 + 15;
const int inf = 0x3f3f3f3f;
vector<int> vec[N];
double dp[N];
int main(){
dp[1] = 0;
vec[1].push_back(1);
for(int i = 1; i < N; i++){
for(int j = 1; i*j < N; j++){
vec[i*j].push_back(j);
}
}
for(int i = 2; i < N; i++){
int m = vec[i].size();
double sum = m;
for(int j = 1; j < m; j++){
sum += dp[vec[i][j]];
}
dp[i] = sum/(m - 1);
}
int t, csn = 1;
scanf("%d", &t);
while(t--){
int idx;
scanf("%d", &idx);
printf("Case %d: %.15f\n", csn++, dp[idx]);
}
}
Dice (III) - LightOJ 1248
题意
求一个骰子各面各出现至少一次所需投掷次数的期望
思路
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 1e6 + 15;
const int inf = 0x3f3f3f3f;
typedef long long ll;
int main(){
int t, csn = 1;
scanf("%d", &t);
while(t--){
double sum = 0;
int n;
scanf("%d", &n);
for(int i = 0; i < n; i++) sum += (double)n/(n - i);
printf("Case %d: %.15f\n", csn++, sum);
}
}