CF767div2A-D
一、题目分析
A.Download More RAM
题意是给定你初始内存,和n个软件,每次运行一个软件如果你能成功运行,你就能得到永久的内存,问你最后能得到的RAM最大值为多少
按软件对内存的需求从小到大排个序,这样你能获得的永久内存越多
1 #include "bits/stdc++.h" 2 using namespace std; 3 struct node { 4 int a,b; 5 }c[1010]; 6 bool cmp(node a,node b) 7 { 8 return a.a < b.a; 9 } 10 int main() 11 { 12 int t; 13 cin >> t; 14 while(t--){ 15 int n,ans; 16 cin >> n >> ans; 17 for(int i = 0;i < n;i++) 18 cin >> c[i].a; 19 for(int i = 0;i < n;i++) 20 cin >> c[i].b; 21 sort(c,c + n,cmp); 22 for(int i = 0;i < n;i++) 23 if(ans >= c[i].a) 24 ans += c[i].b; 25 cout << ans << endl; 26 } 27 return 0; 28 }
B. GCD Arrays
题目要求给你一个区间【l,r】,每次你都可以选择两个数字然后相乘,代替原来的这两个数字,给定你最多的操作次数,问你能不能最后得到a的gcd大于1,如果不能输出NO,如果能输出YES
我们考虑一下特殊情况1-1,这明显是不能的对吧?然后再看一下如果只有1个数字,那么只要是不等于1肯定gcd大于1,所以这是两种情况。
最后考虑一种平常情况,要想gcd大于1,那么这个序列内的数是不能互质的,首先奇数和偶数一定是互质的,那么我们只需要考虑奇数和偶数的数量,奇数变成偶数至少要奇数的个数步,所以我们只需要统计区间内的奇数的个数即可。如果大于k那么则输出NO,否则输出YES
1 #include "bits/stdc++.h" 2 using namespace std; 3 int main() 4 { 5 int t; 6 cin >> t; 7 while(t--){ 8 int l,r,k; 9 cin >> l >> r >> k; 10 if(l == r && l == 1){ 11 cout << "NO" << endl; 12 continue; 13 } 14 if(r - l == 0 && l > 1){ 15 cout << "YES" << endl; 16 continue; 17 } 18 int ji; 19 if(l % 2 == 0 && r % 2 == 0) 20 ji = (r - l) / 2; 21 else if(l % 2 == 1 && r % 2 == 1) 22 ji = (r - l) / 2 + 1; 23 else 24 ji = (r - l + 1) / 2; 25 if(ji > k) 26 cout << "NO" << endl; 27 else 28 cout << "YES" << endl; 29 } 30 return 0; 31 }
C.Meximum Array
题意是给定你一个序列,让你求这个序列的最大字典序的Mex(补集的最小值)集合,问在字典序最大能求的最大Mex集合长度为多少
我们首先要拿一个数组记录出现的数字以及次数,然后用mex不断枚举最大值,什么时候结束呢,当mex的值不存在该数组中时,就可以结束枚举把答案放入ans数组中即可。最重要的是其中枚举mex的过程,用set可以实现更快的查询,我也是做完后看别人做的,也是学习了一波。
1 #include "bits/stdc++.h" 2 const int maxn = 2e5; 3 int bucket[maxn+10]; 4 int a[maxn + 10]; 5 using namespace std; 6 int main() 7 { 8 vector <int> ans; 9 int t; 10 cin >> t; 11 while(t--){ 12 int n; 13 ans.clear(); 14 memset(bucket,0,sizeof(bucket)); 15 cin >> n; 16 for(int i = 0;i < n;i++){ 17 cin >> a[i]; 18 bucket[a[i]]++; 19 } 20 int mex = 0; 21 set <int> vis; 22 for(int i = 0;i < n;i++){ 23 vis.insert(a[i]); 24 bucket[a[i]]--; 25 while(vis.count(mex)) mex++; 26 if(!bucket[mex]){ 27 ans.push_back(mex); 28 mex = 0; 29 vis.clear(); 30 } 31 } 32 cout << ans.size() << endl; 33 for(auto iter = ans.begin();iter != ans.end();iter++) 34 cout << *iter << ' '; 35 cout << endl; 36 } 37 return 0; 38 }
D.Peculiar Movie Preferences
题意很简单,就是给定你n个字符串,问你能否在n个字符串中得到回文字符串,当然你也可以用前面的和后面的拼接起来组成回文串,不难发现这个回文串最多只能由两个字符串组成,然后你发现字符串本身也可能是回文串,有3种情况
一、本身是回文串
1.当字符串长度为1时
2.长度为2时两个相等
3.或者长度为3时,第一个和第三个相等
二、拼接成的回文串(只能用前面的拼后面的)
1.当前字符串长度为2时,能成回文的情况只有前面的串中有和它反过来的,或者说有长度为3的字符串,头两个和它是反过来的
2.当前字符串长度为3是,能成回文的情况有前面有长度为3的字符串和它是反过来的,或者是前面有长度为2的,是当前字符串最后两个反过来的情况
代码实现:
1 #include "bits/stdc++.h" 2 using namespace std; 3 char s[4]; 4 bool ans[27][27]; 5 bool ans2[27][27][27]; 6 int main() 7 { 8 int t; 9 cin >> t; 10 while(t--){ 11 int n; 12 scanf("%d",&n); 13 int flag = 0; 14 memset(ans,0,sizeof(ans)); 15 memset(ans2,0,sizeof(ans2)); 16 while(n--){ 17 scanf("%s",s); 18 int len = strlen(s); 19 if(len == 1) 20 flag = 1; 21 else if(len == 2){ 22 if(s[0] == s[1] || ans[s[1] - 'a'][s[0] - 'a']) 23 flag = 1; 24 else { 25 for(int i = 0;i < 26;i++) 26 if(ans2[s[1] - 'a'][s[0] - 'a'][i]) 27 flag = 1; 28 } 29 ans[s[0] - 'a'][s[1] - 'a'] = 1; 30 } 31 else { 32 if(s[0] == s[2] || ans2[s[2] - 'a'][s[1] - 'a'][s[0] - 'a'] || ans[s[2] - 'a'][s[1] - 'a']) 33 flag = 1; 34 ans2[s[0] - 'a'][s[1] - 'a'][s[2] - 'a'] = 1; 35 } 36 } 37 cout << (flag ? "YES\n" : "NO\n"); 38 } 39 return 0; 40 }
二、总结
这场cf感觉打傻了自己,A题看题目的时候漏了个条件,wa了一发,C题当时没想到用set,D题T了两发,多多补题。
本文来自博客园,作者:{scanner},转载请注明原文链接:{https://home.cnblogs.com/u/scannerkk/}

浙公网安备 33010602011771号