码迷,mamicode.com
首页 > 其他好文 > 详细

2020劳动节训练赛(3)

时间:2020-05-10 21:30:57      阅读:66      评论:0      收藏:0      [点我收藏+]

标签:训练   pre   targe   size   tar   target   相等   小数   字符   

A - Yellow Cards  Gym - 102348A

题目大意:足球比赛,两个队分别有a1,a2名队员,每个队的队员分别得到k1和k2张黄牌罚下,这场比赛一共出示了n张黄牌,问最大和最小罚下多少队员。另外比赛不会中断,即使全场都被罚下(阴   间 比 赛)。

思路:贪心。求最大先罚罚下需要黄牌少的队伍。求最小把全场球员罚到每人只差一张黄牌就会被罚下。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     int a1, a2, k1, k2, n,max=0,min=0;
 5     cin >> a1 >> a2 >> k1 >> k2 >> n;
 6     if (a1 * (k1 - 1) + a2 * (k2 - 1) >= n)min = 0;
 7     else min = n - (a1 * (k1 - 1) + a2 * (k2 - 1));
 8     if (k1 >= k2) {
 9         if (n <= a2 * k2)max = n / k2;
10         else max = a2 + (n - a2 * k2) / k1;
11     }
12     else if (k2 > k1) {
13         if (n <= a1 * k1)max = n / k1;
14         else max = a1 + (n - a1 * k1) / k2;
15     }
16     cout << min << " " << max << endl;
17     return 0;
18 }

 

D - Ticket Game   Gym - 102348D

题目大意:有一个字符串,包含数字和‘?‘,小M和小B在‘?‘处填上任意数字,如果左半边数字和等于右半边数字和,小B胜,否则小M胜利。小M先手,问谁胜。

思路:博弈,分类讨论下,设我是小B,先统计左右两边问号数量和左右数字的和,如果左右数字和一样多,只有左右空一样多时,小M填多少,我小B就跟着填多少,小B必胜,反之小M必胜。

再考虑左右数字和不等的情况:如果左边和小,并且左边空少或和右边空一样多,小M只要疯狂往右塞大数,我小B就gg了。如果左边空多,小M肯定还是疯狂往右塞大数,但我小B还是有机会的,我只要保证当小M把右边塞完大数,只能不得不往左边塞小数时,左边的和可以追上右边我小B就有机会了;但我还是不能保证我能赢,因为如果追上了但超过了该怎么办?所以还要再讨论下。首先,因为是小M先手,所以设本来左边有n个空,右边有m个空,当小M往右边塞完大数时,左边还有n-m个空,这时,是小m先塞,所以如果最后一个空轮到小M塞数的话,他就为所欲为了,我gg。所以如果n-m是奇数,小M必胜。如果n-m为偶数,每轮小M塞0我塞9,左边的和可以追上9,但我朋友小M可不是蠢蛋!他肯定不会让我占据主动,所以,我唯一能保证的是,我可以让每轮我和他的数字和固定增加9。所以,只有剩余轮次*9=左右之差时,才能保证小B胜利右边和小一个道理,就不多赘述了。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int main(){
 4     ios::sync_with_stdio(false);
 5     int n,ff=0;
 6     cin >> n;
 7     string s;
 8     int m,kong_left=0,kong_right=0,sum_left=0,sum_right=0,aihei;
 9     cin >> s;
10     for (int i = 0; i < n / 2; i++) {
11         if (s[i] == ?)kong_left++;
12         else { aihei = s[i] - 0; sum_left += aihei; }
13     }
14     for (int i = n/2; i < n; i++) {
15         if (s[i] == ?)kong_right++;
16         else{ aihei = s[i] - 0; sum_right += aihei; }
17     }
18     if (sum_left > sum_right) {
19         if (kong_left >= kong_right)ff = 1;
20         else {
21             if ((kong_right - kong_left) % 2 != 0)ff = 1;
22             else if ((sum_left - sum_right) != (kong_right - kong_left) / 2 * 9)ff = 1;
23             else ff = 2;
24         }
25     }
26     if (sum_left < sum_right) {
27         if (kong_left <= kong_right)ff = 1;
28         else {
29             if ((kong_left - kong_right) % 2 != 0)ff = 1;
30             else if ((sum_right - sum_left) != (kong_left - kong_right) / 2 * 9)ff = 1;
31             else ff = 2;
32         }
33     }
34     if (sum_left == sum_right) {
35         if (kong_left != kong_right)ff = 1;
36         else ff = 2;
37     }
38     if (ff == 1)cout << "Monocarp" << endl;
39     else cout << "Bicarp" << endl;
40     return 0;
41 }

 

 

F - The Number of Products  Gym - 102348F

题目大意:给一个数组,求分别有多少个子区间乘积为负数,0,正数。

思路:这叫前缀 积?管它的,统计前1~n个数有多少正数,负数,遇到0重新统计。

上代码:

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[200001], c[200001];
 4 int main() {
 5     ios::sync_with_stdio(false);
 6     long long n, sum = 0, ans = 0, fu = 0, zheng = 0, fuz = 0, zeroz = 0, zhengz = 0,change,ka=0;
 7     cin >> n;
 8     a[0] = 0;
 9     for (int i = 1; i <= n; i++) {
10         cin >> c[i];
11         if (c[i] < 0)
12             sum++;
13         a[i] = sum;
14     }
15     for (int i = 1; i <= n; i++) {
16         if (c[i] > 0) {
17             zheng++;
18             zhengz += zheng;
19             fuz += fu;
20             zeroz += ka;
21         }
22         if (c[i] < 0) {
23             change = fu;
24             fu = zheng;
25             zheng = change;
26             fu++;
27             zhengz += zheng;
28             fuz += fu;
29             zeroz += ka;
30         }
31         if (c[i] == 0) {
32             zeroz += i;
33             zheng = 0;
34             fu = 0;
35             ka = i;
36         }
37     }
38     cout << fuz << " " << zeroz << " " << zhengz << endl;
39     return 0;
40 }

 

 

G - Swap Letters  Gym - 102348G 

题目大意:给两个只有字符a和b的长度相等字符串,从两个字符串分别选一个字符进行交换多次,问至少交换多少次能使两字符串相等,若不能就打印-1.

思路:统计两字符串相同下标的组合分别的数量,aa和bb这种不要管,因为没必要换,只要求ab和ba的数量。ab和ba数量的和若为奇数,便无法通过交换使两字符串相同。别忘了记录下标,因为要输出方法。

代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 int a[200001] = {0}, b[200001] = { 0 };
 4 int main(){
 5     int n,ans1=0,ans2=0;
 6     string s1, s2;
 7     cin >> n;
 8     cin >> s1 >> s2;
 9     for (int i = 0; i < n; i++) {
10         if (s1[i] == a && s2[i] == b) { a[ans1] = i + 1; ans1++; }
11         if (s1[i] == b && s2[i] == a) { b[ans2] = i + 1; ans2++; }
12     }
13     if (ans1%2==0&&ans2%2!=0|| ans2 % 2 == 0 && ans1 % 2 != 0)cout << "-1" << endl;
14     else {
15         if (ans1 % 2 == 0) {
16             cout << ans1 / 2 + ans2 / 2 << endl;
17             for (int i = 0; i < ans1; i = i + 2)
18                 cout << a[i] << " " << a[i + 1] << endl;
19             for (int i = 0; i < ans2; i = i + 2)
20                 cout << b[i] << " " << b[i + 1] << endl;
21         }
22         else {
23             cout << ans1 / 2 + ans2 / 2+2 << endl;
24             for (int i = 0; i < ans1-1; i = i + 2)
25                 cout << a[i] << " " << a[i + 1] << endl;
26             for (int i = 0; i < ans2-1; i = i + 2)
27                 cout << b[i] << " " << b[i + 1] << endl;
28             cout << a[ans1 - 1] << " " << a[ans1- 1] << endl;
29             cout << a[ans1 - 1] << " " << b[ans2 - 1] << endl;
30         }
31     }
32     return 0;
33 }

 

I - Moonbound

阅读理解题,奇怪的坑,不放代码了,注意不要1和2分别全部输出。

 

2020劳动节训练赛(3)

标签:训练   pre   targe   size   tar   target   相等   小数   字符   

原文地址:https://www.cnblogs.com/Sympa/p/12864864.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!