CodeForces Round #293 Div.2
A. Vitaly and Strings
题意:
给出两个长度相同的字符串,问是否存在一个字符串,该串的字典序大于输入的第一个串 且 小于第二个串。
分析:
找出比第一个串大一的串,看看它是否小于第二个串,是的话就满足,否则不存在这样的串。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 110; 5 6 char s1[maxn], s2[maxn]; 7 8 int main() 9 { 10 //freopen("in.txt", "r", stdin); 11 12 scanf("%s%s", s1, s2); 13 int l = strlen(s1); 14 int i = l-1; 15 s1[i] += 1; 16 bool flag = false; 17 while(i > 0 && s1[i] > 'z') 18 { 19 s1[i] -= 26; 20 s1[--i] += 1; 21 } 22 if(s1[0] > 'z') { puts("No such string"); return 0; } 23 for(int i = 0; i < l; ++i) if(s1[i] < s2[i]) { flag = true; break; } 24 25 if(flag) printf("%s\n", s1); 26 else puts("No such string"); 27 28 return 0; 29 }
B. Tanya and Postcard
题意:
从两个字符串中各取一个字符进行匹配,如果两个字符相同,则记作一个YAY,如果仅大小写不同,则记作一个WHOOPS。
求在YAY最多的前提下,WHOOPS最多是多少。
分析:
首先扫一遍两个串,统计一下各个字符的个数,先将所有的相同字符进行匹配,这样YAY最多。然后在剩下没有匹配的字符中,找A和a等进行匹配。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 200000 + 10; 5 6 char s[maxn], t[maxn]; 7 int sum1[256], sum2[256]; 8 9 int ID(int x) 10 { 11 if(x < 26) return 'a' + x; 12 return 'A' + x - 26; 13 } 14 15 int ID2(int x) 16 { 17 if(x < 26) return 'A' + x; 18 return 'a' + x - 26; 19 } 20 21 int main() 22 { 23 //freopen("in.txt", "r", stdin); 24 25 scanf("%s%s", s, t); 26 int ls = strlen(s); 27 int lt = strlen(t); 28 29 for(int i = 0; i < ls; ++i) sum1[s[i]]++; 30 for(int i = 0; i < lt; ++i) sum2[t[i]]++; 31 32 int yay = 0, whoops = 0; 33 34 for(int i = 0; i < 52; ++i) 35 { 36 int ind = ID(i); 37 int t = min(sum1[ind], sum2[ind]); 38 yay += t; 39 sum1[ind] -= t; sum2[ind] -= t; 40 41 } 42 43 for(int i = 0; i < 52; ++i) 44 { 45 int ind1 = ID(i); 46 int ind2 = ID2(i); 47 int t = min(sum1[ind1], sum2[ind2]); 48 sum1[ind1] -= t; sum2[ind2] -= t; 49 whoops += t; 50 } 51 52 printf("%d %d\n", yay, whoops); 53 54 return 0; 55 }
C. Anya and Smartphone (模拟)
题意:
智能手机上有n个APP,每个屏幕恰好放k个APP(最后一个可能放不满)。启动第i页屏幕(编号从1开始)的APP需要操作i个手势,手机还有个特点就是启动完某个APP后会和前面相邻的那个交换位置,启动第一个APP除外。
按顺序给出这些APP的编号,和启动顺序,问总共需要多少个操作手势。
分析:
为了快速计算出每个APP的编号和位置,我们开两个数组 id 和 pos,分别记录 每个位置上APP的编号 和 对应编号APP所在的位置。
在交换的时候,既要交换两个位置对应的id,又要交换两个APP对应id所在的位置。
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 100000 + 10; 5 6 int n, m, k; 7 long long ans = 0; 8 9 int id[maxn], pos[maxn]; 10 11 int main() 12 { 13 //freopen("in.txt", "r", stdin); 14 15 scanf("%d%d%d", &n, &m, &k); 16 17 for(int p = 0; p < n; ++p) 18 { 19 int x; 20 scanf("%d", &x); 21 id[p] = x; 22 pos[x] = p; 23 } 24 25 for(int i = 0; i < m; ++i) 26 { 27 int x; 28 scanf("%d", &x); 29 int p = pos[x]; 30 ans += p / k + 1; 31 if(p == 0) continue; 32 int y = id[p-1]; 33 swap(pos[x], pos[y]);//交换位置 34 swap(id[p], id[p-1]);//交换编号 35 } 36 37 printf("%I64d\n", ans); 38 39 return 0; 40 }
D. Ilya and Escalator (概率DP)
题意:
有n个人排成一队,每经过一秒会有p的概率队首的那个人乘上电梯,1-p的概率队首的人没有上电梯。这里假设电梯无限长,因此不考虑上电梯的人下来的情况。
问t秒后,电梯人数的期望。
分析:
第一次学会用DP的方法求概率。
设d(i, j)为第i秒后,电梯上有j个人的概率。
初始状态:d(1, 1) = p, d(1, 0) = 1-p
当j == n时,所有的人都已上电梯,则d(i+1, j) += d(i, j)
否则,p的概率上电梯,则有d(i+1, j+1) += d(i, j) * p
1-p的概率不上电梯,d(i+1, j) += d(i, j) * (1-p)
最后所求期望就是Σd(t, j) * j (0≤j≤n)
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int maxn = 2000 + 10; 5 6 double d[maxn][maxn]; 7 8 int main() 9 { 10 int n, t; 11 double p; 12 scanf("%d%lf%d", &n, &p, &t); 13 14 d[1][1] = p; d[1][0] = 1.0 - p; 15 for(int i = 2; i <= t; i++) 16 for(int j = 0; j <= n; j++) 17 { 18 if(j == n) d[i][j] += d[i-1][j]; 19 else 20 { 21 d[i][j + 1] += d[i-1][j] * p; 22 d[i][j] += d[i-1][j] * (1.0 - p); 23 } 24 } 25 26 double ans = 0; 27 28 for(int i = 0; i <= n; i++) ans += d[t][i] * i; 29 30 printf("%.8f\n", ans); 31 32 return 0; 33 }