2017-2018 ACM-ICPC Latin American Regional Programming Contest
题面pdfhttps://codeforc.es/gym/101889/attachments/download/7471/statements-2017-latam-regional.pdf
zyn感冒,两个人打。刚开始两题超迅速,40分钟后开始各种写不出,自闭。然后突然又开出两题。
4题全部1A,70名左右应该能稳个银。
说明卡题了可千万不能放弃!虽然可能简单题做不出来,过的多的题目做不出来,也不要放弃去开题。
以及周末这两场都说明一定要胆子大。
B---Buggy ICPC【找规律】
题意:
输入一串字符串,当遇到元音的时候前面输入的所有字符包括这个元音都反转一下。现在给定最后的结果字符串,问有多少种输入方法可以得到这个字符串。
思路:
czc去打了个表,然后我们疯狂找规律。真的找到规律了
如果没有元音,当然是1.如果有元音,但是第一个不是元音,一定是0
其他情况,答案就是中间两个元音之间的辅音个数$+1$。
只有一个元音时默认后面还有一个元音结尾,答案就是字符串长度。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 const int maxn = 1e5 + 5; 6 char t[maxn]; 7 vector<int>pos_of_vowel; 8 char vowel[5] = {'a', 'e', 'i', 'o', 'u'}; 9 10 int main() 11 { 12 while(scanf("%s", t) != EOF){ 13 pos_of_vowel.clear(); 14 int len = strlen(t), cnt = 0; 15 for(int i = 0; i < len; i++){ 16 for(int j = 0; j < 5; j++){ 17 if(t[i] == vowel[j]){ 18 cnt++; 19 pos_of_vowel.push_back(i); 20 } 21 } 22 } 23 24 if(cnt == 0){ 25 printf("1\n"); 26 } 27 else{ 28 bool flag = false; 29 for(int i = 0; i < 5; i++){ 30 if(t[0] == vowel[i]){ 31 flag = true; 32 break; 33 } 34 } 35 if(!flag){ 36 printf("0\n"); 37 } 38 else{ 39 if(cnt == 1){ 40 printf("%d\n", len); 41 } 42 else{ 43 int id = (cnt + 1) / 2; 44 //cout<<id<<endl<<pos_of_vowel[id]<<endl<<pos_of_vowel[id - 1]<<endl; 45 int l = pos_of_vowel[id] - pos_of_vowel[id - 1]; 46 printf("%d\n", l); 47 } 48 49 } 50 } 51 } 52 return 0; 53 }
H---Hard Choice【水题】
题意:
【略】
思路:
【略】
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 //#include<bits/stdc++.h> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<algorithm> 8 #include<queue> 9 #include<vector> 10 #include<set> 11 #include<climits> 12 #include<map> 13 using namespace std; 14 typedef long long LL; 15 #define N 100010 16 #define pi 3.1415926535 17 #define inf 0x3f3f3f3f 18 19 int a, b, c; 20 21 int main() 22 { 23 while(scanf("%d%d%d", &a, &b, &c) != EOF){ 24 int x, y, z; 25 scanf("%d%d%d", &x, &y, &z); 26 int ans = 0; 27 if(x > a){ 28 ans += x - a; 29 } 30 if(y > b){ 31 ans += y - b; 32 } 33 if(z > c){ 34 ans += z - c; 35 } 36 printf("%d\n", ans); 37 } 38 }
C---Complete Naebbirac's sequence【暴力】
题意:
有$n$个$1$到$k$之间的数。可以进行一下三种操作一次(只能一次):1、删去其中一个。2、添加一个$1$到$k$的数。3、将其中一个换成另一个$1$到$k$的数。使得他们出现的次数都一样。
思路:
因为只能操作一次。所以每种操作都讨论一下就行了。
首先统计一下每个数出现的次数,按照次数从小到大排序。
1、把第一个数次数加1,看所有数是否满足次数相同。
2、把最后一个数次数减1,看所有数是否满足次数相同。
3、把第一个数次数加1,最后一个数次数减1,看所有数是否满足次数相同。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 //#include<bits/stdc++.h> 3 #include<cstdio> 4 #include<cmath> 5 #include<cstdlib> 6 #include<cstring> 7 #include<algorithm> 8 #include<queue> 9 #include<vector> 10 #include<set> 11 #include<climits> 12 #include<map> 13 using namespace std; 14 typedef long long LL; 15 #define N 100010 16 #define pi 3.1415926535 17 #define inf 0x3f3f3f3f 18 19 int n, k; 20 const int maxn = 1e4 + 5; 21 int num[maxn]; 22 struct node{ 23 int num, cnt; 24 }se[1005]; 25 26 bool cmp(node a, node b) 27 { 28 return a.cnt < b.cnt; 29 } 30 31 int main() 32 { 33 while(scanf("%d%d", &k, &n) != EOF){ 34 for(int i = 0; i < 1005; i++){ 35 se[i].num = i; 36 se[i].cnt = 0; 37 } 38 for(int i = 0; i < n; i++){ 39 scanf("%d", &num[i]); 40 se[num[i]].cnt++; 41 } 42 43 sort(se + 1, se + k + 1, cmp); 44 bool flag = true; 45 se[1].cnt++; 46 for(int i = 1; i <= k-1; i++){ 47 if(se[i].cnt != se[i + 1].cnt){ 48 flag = false; 49 break; 50 } 51 } 52 if(flag){ 53 printf("+%d\n", se[1].num); 54 } 55 else{ 56 se[k].cnt--; 57 bool flag2 = true; 58 for(int i = 1; i <= k - 1; i++){ 59 if(se[i].cnt != se[i + 1].cnt){ 60 flag2 = false; 61 break; 62 } 63 } 64 if(flag2){ 65 printf("-%d +%d\n", se[k].num, se[1].num); 66 } 67 else{ 68 se[1].cnt--; 69 bool flag3 = true; 70 for(int i = 1; i <= k - 1; i++){ 71 if(se[i].cnt != se[i + 1].cnt){ 72 flag3 = false; 73 break; 74 } 75 } 76 if(flag3){ 77 printf("-%d\n", se[k].num); 78 } 79 else{ 80 printf("*\n"); 81 } 82 } 83 } 84 } 85 }
J---Jumping Frog【数论】【环形dp】
题意:
有n个位子,有的是石头(R), 有的是池塘(P)。青蛙只能在石头上跳,不能跳到池塘里去。每次他选择一个k,表示他每次跳k步,希望他可以跳回到起点。问以所有的位子为起点,一共能有多少种不同的k的选择。
思路:
这题是真的没思路。czc自己刷刷刷就敲完1A了。附一下他的代码。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 const int MAX_N = 1e5 + 5; 5 6 int N; 7 char S[MAX_N]; 8 9 vector <int> factor; 10 void getFactors(int N) 11 { 12 factor.clear(); 13 for (int i = 1; i <= N/i; i++) { 14 if (N%i == 0) { 15 factor.push_back(i); 16 if (i*i != N) 17 factor.push_back(N/i); 18 } 19 } 20 sort(factor.begin(), factor.end()); 21 } 22 23 bool f[MAX_N << 1][50]; 24 bool can_jump[MAX_N]; 25 void dp() 26 { 27 int cnt = factor.size(); 28 memset(f, false, sizeof f); 29 for (int i = 1; i <= 2*N; i++) { 30 for (int j = 0; j < cnt; j++) { 31 int tmp = factor[j]; 32 if (S[(i-1)%N] == 'P') 33 f[i][j] = false; 34 else if (S[(i-1)%N] == 'R') { 35 if (i-tmp <= 0) 36 f[i][j] = true; 37 else 38 f[i][j] = f[i-tmp][j]; 39 } 40 } 41 } 42 43 memset(can_jump, false, sizeof can_jump); 44 for (int i = N+1; i <= 2*N; i++) { 45 for (int j = 0; j < cnt; j++) { 46 int tmp = factor[j]; 47 if (f[i][j]) 48 can_jump[tmp] = true; 49 } 50 } 51 } 52 53 inline int gcd(int a, int b) 54 { 55 return a%b ? gcd(b, a%b) : b; 56 } 57 58 int main() 59 { 60 scanf("%s", S); 61 N = strlen(S); 62 getFactors(N); 63 dp(); 64 65 int ans = 0; 66 for (int k = 1; k <= N-1; k++) { 67 int g = gcd(k, N); 68 if (can_jump[g]) 69 ans++; 70 } 71 cout << ans << endl; 72 return 0; 73 }