训练赛13
A - Amsopoly Simple Version Gym - 102279A
题目大意:三人轮流掷骰子玩大富翁游戏,具体的游戏地图如下图。每人移动点数是固定的,移动到空格占领,自己的格子无事,别人的格子交罚款。问出现有人交罚款时,三人一共移动了多少次。
若永远不会有人被罚款,则输出3000000000。
思路:移动占领直接模拟,主要问题是在如何判断永远不会罚款的情况。我的做法是当他们三人都走过自己之前占领过的格子时,若还没人被罚款,就一定不会有人被罚款了。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int k[100010]; 4 int main() { 5 std::ios::sync_with_stdio(false); 6 int n, v1, v2, v3,ans=0,flag1=0,a=0,b=0,c=0,flag2=0,flag3=0; 7 cin >> n >> v1 >> v2 >> v3; 8 n++; 9 while (flag1==0||flag2==0||flag3==0) { 10 a = (a + v1) % n; 11 ans++; 12 if (a > 0) { 13 if (k[a] == 2 || k[a] == 3)break; 14 else if (k[a] == 1)flag1 = 1; 15 else if (k[a] == 0)k[a] = 1; 16 } 17 b = (b + v2) % n; 18 ans++; 19 if (b > 0) { 20 if (k[b] == 1 || k[b] == 3)break; 21 else if (k[b] == 2)flag2 = 1; 22 else if (k[b] == 0)k[b] = 2; 23 } 24 c = (c + v3) % n; 25 ans++; 26 if (c > 0) { 27 if (k[c] == 1 || k[c] == 2)break; 28 else if (k[c] == 3)flag3 = 1; 29 else if (k[c] == 0)k[c] = 3; 30 } 31 } 32 if (flag1 == 1 && flag2 == 1 && flag3 == 1)cout << "3000000000" << endl; 33 else cout << ans << endl; 34 return 0; 35 }
D - Dahlia The Champion Gym - 102279D
题目大意:游戏里的一个角色,技能是钩向任一方向直线上的第一个目标,现在给出技能范围、n个目标和它们的笛卡尔坐标,求有多少目标会被钩中。
思路:挺烦的一道题。将目标坐标用目标位置和施法位置的差来表示,消除如果施法位置不在原点难以比较的问题。其次,即使两点在同一直线上,如果它们分别处于施法位置的两侧,那么都可以钩到,
因此,可以用x表示目标所在正负方向,y表示所在直线斜率;特别地,x=0时求斜率会出现除零错误,可以将斜率设为一个很大的值。最后结构体排序扫一遍就好了。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 long long b[500001], c[500001]; 4 struct node { 5 double x, y; 6 }; 7 node d[500001]; 8 bool cmp(node d1, node d2) { 9 if(d1.x!=d2.x) 10 return d1.x < d2.x; 11 else return d1.y < d2.y; 12 } 13 int main() { 14 ios::sync_with_stdio(false); 15 long long x, y, r, n; 16 cin >> x >> y >> r >> n; 17 long long sum = 0, ans = 0,bb,cc,error=0; 18 for (int i = 0; i < n;i++) { 19 cin >> b[i] >> c[i]; 20 bb = b[i] - x; 21 cc = c[i] - y; 22 if (bb*bb+cc*cc <= r * r) { 23 if (bb == 0) { 24 d[ans].x = 0; 25 if(y<0) d[ans].y = -77777777; 26 else d[ans].y = 77777777; 27 } 28 else if (bb > 0) { 29 d[ans].x = 1.0; 30 d[ans].y = cc * 1.0 / bb; 31 } 32 else { 33 d[ans].x = -1.0; 34 d[ans].y = cc * 1.0 / -bb; 35 } 36 ans++; 37 } 38 } 39 sort(d, d + ans, cmp); 40 if (ans != 0)sum++; 41 for (int i = 1; i < ans; i++) 42 if (d[i].y != d[i - 1].y)sum++; 43 cout << sum << endl; 44 return 0; 45 }
I - Jumpity Digits Gym - 102279J
题目大意:给一个数字(最多100位),换两位,求比它小的最大数字。
思路:难题不会,水题做法贼多。最简单就是倒着扫一遍,找到第一个递增的数位,和后面比它小的最大的换一下,当然换首位要保证不能换成0。
代码:
1 #include <bits/stdc++.h> 2 using namespace std; 3 int main() { 4 ios::sync_with_stdio(false); 5 string s; 6 int n,flag=0,r,l; 7 cin >> s; 8 n = s.length(); 9 char p; 10 for (int i = n-2; i >0; i--) { 11 int min = -1; 12 for (int j = n - 1; j > i; j--) { 13 if (s[j] - '0' < s[i] - '0' && s[j] - '0' >= min) { 14 min = s[j] - '0'; 15 r = j; 16 } 17 } 18 if (min != -1) { 19 p = s[i]; 20 s[i] = s[r]; 21 s[r] = p; 22 flag = 1; 23 break; 24 } 25 } 26 if (flag == 0) { 27 int min = -1; 28 for (int j = n - 1; j > 0; j--) { 29 if (s[j] - '0' < s[0] - '0' && s[j] - '0' >= min && s[j] - '0' != 0) { 30 min = s[j] - '0'; 31 r = j; 32 } 33 } 34 if (min != -1) { 35 p = s[0]; 36 s[0] = s[r]; 37 s[r] = p; 38 flag = 1; 39 } 40 } 41 if (flag == 0)cout << -1 << endl; 42 else cout << s << endl; 43 return 0; 44 }
训练赛14
A - Is It Easy ? Gym - 102263A
虽然我是蒟蒻我也不会给一个a*b写题解吧?
B - Road to Arabella Gym - 102263B
题目大意:小A声明一个正整数n,小K声明一个正整数k(1<=k<=n),两人轮流从n减去x,设当前的n为m,则1<=x<=max(1,m-k),谁拿到最后的数谁赢,现在给出n和k,问小K先手,谁赢?
思路:博弈论。分类讨论一下,怎样小K是必输的?n是偶数,但x只能等于1,必输。否则的话,小K先手拿第一次,一定可以掌控剩下数目,使得接下来每人只能拿1并且剩下的一定是奇数。小K便必赢。
代码(当时写的有点多余):
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() { 4 std::ios::sync_with_stdio(false); 5 int t; 6 cin >> t; 7 while (t--) { 8 int n, k; 9 cin >> n >> k; 10 if (k == 1) { 11 if (n == 2)cout << "Ayoub" << endl; 12 else cout << "Kilani" << endl; 13 } 14 else { 15 if (n - k <= 1) { 16 if(n%2==0)cout << "Ayoub" << endl; 17 else cout << "Kilani" << endl; 18 } 19 else { 20 cout << "Kilani" << endl; 21 } 22 } 23 } 24 return 0; 25 }
E - Card Game Gym - 102263G
题目大意:n张牌上有1到n数字,小Z和小E各拿一张比点数,点数高的得到自己牌点数的分数,求小E在所有可能情况下得到分数的期望。
思路:数学期望等于发生概率乘结果的和。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() { 4 std::ios::sync_with_stdio(false); 5 double n, sum = 0.0; 6 cin >> n; 7 for (double i = 2.0; i <= n+0.1; i=i+1.0) { 8 sum += (i - 1) * i/n; 9 } 10 printf("%.10f\n", sum); 11 return 0; 12 }
F - Steaks Gym - 102263H
题目大意:n张牛排k个锅,每张牛排有两面,每面要加热5分钟,每个锅能同时加热2张牛排。问全部加热完要几分钟。
思路:每个锅同时加热2张,看成一共有2k个锅就行了。分步走,第一步,将所有牛排都加热一遍,这里要分类讨论,如果牛排张数少于2k,那么剩余的空闲锅就不能运作。否则需要算出最后一轮加热第一面牛排还剩几个锅,让它们用来加热目前没在锅上的牛排的第二面。第二步,加热第二面就行了。
代码(这里更简单了,把每张牛排看成2张,排除一轮就能热完第一面的情况就好):
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() { 4 std::ios::sync_with_stdio(false); 5 long long n, k; 6 cin >> n >> k; 7 if (n / k < 2)cout << "10" << endl; 8 else { 9 if (n * 2 % (k * 2) == 0)cout << 5 * (n / k ) << endl; 10 else cout << 5 * (n / k + 1 ) << endl; 11 } 12 return 0; 13 }
H - Thanos Power Gym - 102263J
题目大意:灭霸种花。一次可以种或移除10的x次方朵花,问种N朵花至少要几步。
思路:一开始想用贪心,结果发现贪心要不就是改变了之前的状态,要不就是贪的不够。所以只能用DP。
定义状态:dp[i][0]为到i位不进位最小花费,dp[i][1]为到i位向上进一位后再退位的最小花费。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int dp[100010][2]; 4 int main() { 5 std::ios::sync_with_stdio(false); 6 string s; 7 cin >> s; 8 int n = s.length(); 9 dp[n - 1][0] = s[n - 1] - '0'; 10 dp[n - 1][1] = 10 - (s[n - 1] - '0'); 11 for (int i = n - 2; i >= 0; i--) { 12 dp[i][0] = min(dp[i + 1][0], dp[i + 1][1]+1) + s[i] - '0'; 13 dp[i][1] = min(dp[i + 1][0], dp[i + 1][1]-1) + 10-(s[i] - '0'); 14 } 15 cout << min(dp[0][0], dp[0][1]+1) << endl; 16 return 0; 17 }
I - Two Operations Gym - 102263M
题目大意:给一个小写字母字符串,两种操作:1.交换两个字母2.可以把两个相邻的相同字母变成下一个字母(当然z除外),问可得到结果的最大字典序。
思路:记录每种字母数量,从头到尾变一遍,别忘了变完后要给下一个加上去。然后从后往前输出字母即可。
代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 int main() { 4 std::ios::sync_with_stdio(false); 5 int a[30]; 6 string s; 7 cin >> s; 8 memset(a, 0, sizeof(a)); 9 for (int i = 0; i < s.length(); i++) { 10 a[s[i] - 'a']++; 11 } 12 for (int i = 0; i < 25; i++) { 13 if (a[i] / 2 > 0) { 14 a[i + 1] += (a[i] / 2); 15 a[i] =a[i]%2; 16 } 17 } 18 for (int i = 25; i >= 0; i--) { 19 for (int j = 0; j < a[i]; j++) 20 cout << (char)(i + 'a'); 21 } 22 cout << endl; 23 return 0; 24 }