题1: Uva 1636 Headshot
题目大意:
给出一个000111序列,注意实际上是环状的。问是0出现的概率大,还是当前是0,下一个还是0的概率大。
问题比较简单,注意比较大小: A/C > B/D <=> A * D > B * C
1 #include <cstdio> 2 #include <cstring> 3 #include <cstdlib> 4 #include <algorithm> 5 #include <iostream> 6 7 using namespace std; 8 9 char str[205]; 10 11 void Solve(){ 12 int len = strlen(str); 13 int cnt1 = 0, cnt2 = 0; 14 15 for(int i = 0; i < len; ++ i){ 16 if(i == len - 1){ 17 if(str[i] == '0') ++ cnt1; 18 if(str[i] == '0' && str[0] == '0') ++ cnt2; 19 } 20 else{ 21 if(str[i] == '0') ++ cnt1; 22 if(str[i] == '0' && str[i + 1] == '0') ++ cnt2; 23 } 24 } 25 26 if(cnt2 * len > cnt1 * cnt1) puts("SHOOT"); 27 else if(cnt2 * len < cnt1 * cnt1) puts("ROTATE"); 28 else puts("EQUAL"); 29 } 30 31 int main(){ 32 while(scanf("%s", str) != EOF){ 33 Solve(); 34 } 35 36 return 0; 37 }
题2: Uva 1637 Double Patience
扑克牌拿牌问题。开一个9维的数组,记忆化搜索。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 double f[5][5][5][5][5][5][5][5][5]; 6 bool vi[5][5][5][5][5][5][5][5][5]; 7 char str[4][5], poker[10][5]; 8 9 double dfs(int p1, int p2, int p3, int p4, int p5, int p6, int p7, int p8, int p9){ 10 if(vi[p1][p2][p3][p4][p5][p6][p7][p8][p9]) 11 return f[p1][p2][p3][p4][p5][p6][p7][p8][p9]; 12 vi[p1][p2][p3][p4][p5][p6][p7][p8][p9] = true; 13 14 bool flag = false; 15 int top[11] = {0, p1, p2, p3, p4, p5, p6, p7, p8, p9}; 16 double &x = f[p1][p2][p3][p4][p5][p6][p7][p8][p9]; 17 18 for(int i = 1; i <= 9; ++ i) 19 if(top[i]){ 20 flag = true; 21 break; 22 } 23 if(!flag) 24 return x = 1.0; 25 26 int cnt = 0; 27 double sumper = 0; 28 29 for(int i = 1; i <= 9; ++ i){ 30 if(top[i]){ 31 for(int j = i + 1; j <= 9; ++ j){ 32 if(top[j] && poker[i][top[i]] == poker[j][top[j]]){ 33 cnt ++; 34 top[i] --; top[j] --; 35 36 sumper += dfs(top[1], top[2], top[3], top[4], top[5], top[6], top[7], top[8], top[9]); 37 38 top[i] ++; top[j] ++; 39 } 40 } 41 } 42 } 43 44 if(sumper > 0) x = (double) sumper / cnt; 45 46 return x; 47 } 48 49 50 int main(){ 51 while(~scanf("%s%s%s%s", str[0], str[1], str[2], str[3])){ 52 memset(f, 0, sizeof f); 53 memset(vi, false, sizeof vi); 54 55 for(int i = 1; i <= 4; ++ i) 56 poker[1][i] = str[i -1][0]; 57 for(int i = 1; i <= 8; ++ i){ 58 scanf("%s%s%s%s", str[0], str[1], str[2], str[3]); 59 for(int j = 1; j <= 4; ++ j) 60 poker[i + 1][j] = str[j - 1][0]; 61 } 62 63 dfs(4, 4, 4, 4, 4, 4, 4, 4, 4); 64 65 printf("%.6lf\n", f[4][4][4][4][4][4][4][4][4]); 66 } 67 68 return 0; 69 }
题3:Uva 1639 Candy
题目大意:
两盒子糖,每盒中都有N个,在一个盒子中取的概率是p,另一个是1-p,求一个盒子没有糖之后另一个盒子剩的糖数的期望。
式子不难列,高中数学期望会考。但是主要是计算,组合数是极大数,概率又是极小数,计算机算的话要取对数,把大数化小,小数化大,乘法变加,
除法变减。 注意精度。不要为了简化代码新定义变量等于一长串代码中的一部分,会挂精度。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int N = 400000 + 5; 6 7 int n, cnt = 0; 8 double p; 9 long double fac[N]; 10 11 int main(){ 12 13 fac[1] = 0; 14 for(int i = 2; i <= 400000; ++ i) 15 fac[i] = fac[i - 1] + log(i); 16 17 while(~scanf("%d%lf", &n, &p)){ 18 double ans = 0; 19 20 ++ cnt; 21 if(p == 0 || p == 1){ 22 printf("Case %d: %.6lf\n", cnt, (double) n); 23 continue; 24 } 25 26 int U = 2 * n; 27 28 for(int i = 0; i <= n; ++ i){ 29 ans += exp(fac[U - i] - fac[n] - fac[n - i] + log(p) * (n + 1) + log(1 - p) * (n - i)) * i + exp(fac[U - i] - fac[n] - fac[n - i] + log(p) * (n - i) + log(1 - p) * (n + 1)) * i; 30 } 31 32 printf("Case %d: %.6lf\n", cnt, ans); 33 } 34 35 return 0; 36 }