Contest - 2014 SWJTU ACM 手速测试赛(2014.10.31)
题目列表:
2146 Problem A | 【手速】阔绰的Dim |
2147 Problem B | 【手速】颓废的Dim |
2148 Problem C | 【手速】我的滑板鞋 |
2149 Problem D | 【手速】潦倒的Dim |
2150 Problem E | 【手速】被NTR的Dim |
2146 Problem A:
简单的最长回文串统计算法,这里没有过高要求,n^2算法可以AC。其中包括dp动规以及中心法(以上两种都是O(n^2)算法,可以参考白书)。推广,可以尝试扩展KMP(O(nlogn))或者Manacher算法(O(n))。可以查阅相关资料自行选择学习。这里给出中心法。
1 /****************************************/ 2 /***** Desgard_Duan *****/ 3 /****************************************/ 4 //#pragma comment(linker, "/STACK:102400000,102400000") 5 #define _CRT_SECURE_NO_WARNINGS 6 #include <iostream> 7 #include <cstdio> 8 #include <cstdlib> 9 #include <cstring> 10 #include <string> 11 #include <algorithm> 12 #include <stack> 13 #include <map> 14 #include <queue> 15 #include <vector> 16 #include <set> 17 #include <functional> 18 #include <cmath> 19 #include <numeric> 20 21 using namespace std; 22 23 char s[500]; int len; 24 25 inline void get_val(int &a) { 26 int value = 0, s = 1; 27 char c; 28 while ((c = getchar()) == ' ' || c == '\n'); 29 if (c == '-') s = -s; else value = c - 48; 30 while ((c = getchar()) >= '0' && c <= '9') 31 value = value * 10 + c - 48; 32 a = s * value; 33 } 34 35 int tofind(int h, int t) { 36 int re = t - h + 1; 37 while (h < t) { 38 if (s[h++] != s[t--]) return 0; 39 } 40 return re; 41 } 42 43 int main() { 44 //freopen("huiwen.in", "r", stdin); 45 //freopen("huiwen.out","w",stdout); 46 int T; 47 cin >> T; 48 while (T--) { 49 scanf("%s", s); 50 len = strlen(s); 51 int ans = 1; 52 for (int i = 0; i < len - 1; i++) 53 for (int j = i + 1; j < len; j++) { 54 ans = max(ans, tofind(i, j)); 55 } 56 cout << ans << endl; 57 } 58 return 0; 59 }
2147 Problem B:
一道字符串水题,只要按位置遍历一遍即可。C语言基础题。
1 /****************************************/ 2 /***** Desgard_Duan *****/ 3 /****************************************/ 4 //#pragma comment(linker, "/STACK:102400000,102400000") 5 #define _CRT_SECURE_NO_WARNINGS 6 #include <iostream> 7 #include <cstdio> 8 #include <cstdlib> 9 #include <cstring> 10 #include <string> 11 #include <algorithm> 12 #include <stack> 13 #include <map> 14 #include <queue> 15 #include <vector> 16 #include <set> 17 #include <functional> 18 #include <cmath> 19 #include <numeric> 20 21 using namespace std; 22 23 inline void get_val(int &a) { 24 int value = 0, s = 1; 25 char c; 26 while ((c = getchar()) == ' ' || c == '\n'); 27 if (c == '-') s = -s; 28 else value = c - 48; 29 while ((c = getchar()) >= '0' && c <= '9') 30 value = value * 10 + c - 48; 31 a = s * value; 32 } 33 34 string str1, str2; 35 int main () { 36 int T; 37 //cin >> T; 38 while (cin >> str1 >> str2) { 39 40 int ans = 0; 41 for (int i = 0 ; i < str1.size(); ++ i) { 42 if (str1[i] == str2[i]) { 43 ans ++; 44 } 45 } 46 cout << ans << endl; 47 } 48 return 0; 49 }
2148 Problem C:
一道贪心的白书例题,类型归类为查找不相交区间的最大个数。具体思路:对于相交的任意两个区间分为两种情况(图A、图B)。若出现情况A,直接将大区间删除即可。若出现情况B,我们先将集合按照x进行升序排列,然后优先选取x最小的情况B中的区间,这样可以得到最佳的方案。
1 /****************************************/ 2 /***** Desgard_Duan *****/ 3 /****************************************/ 4 //#pragma comment(linker, "/STACK:102400000,102400000") 5 #define _CRT_SECURE_NO_WARNINGS 6 #include <iostream> 7 #include <cstdio> 8 #include <cstdlib> 9 #include <cstring> 10 #include <string> 11 #include <algorithm> 12 #include <stack> 13 #include <map> 14 #include <queue> 15 #include <vector> 16 #include <set> 17 #include <functional> 18 #include <cmath> 19 #include <numeric> 20 21 using namespace std; 22 23 inline void get_val(int &a) { 24 int value = 0, s = 1; 25 char c; 26 while ((c = getchar()) == ' ' || c == '\n'); 27 if (c == '-') s = -s; 28 else value = c - 48; 29 while ((c = getchar()) >= '0' && c <= '9') 30 value = value * 10 + c - 48; 31 a = s * value; 32 } 33 34 vector<pair<int, int> > shoes; 35 bool flag[1005]; 36 37 int main () { 38 int n, x, y; 39 //freopen("out.txt", "w", stdout); 40 while (~scanf ("%d", &n)) { 41 shoes.clear(); 42 for (int i = 0; i < n; ++ i) { 43 cin >> x >> y; 44 shoes.push_back (make_pair(x, y)); 45 } 46 sort (shoes.begin(), shoes.end()); 47 48 memset (flag, 0, sizeof (flag)); 49 for (int i = 0; i < n; ++ i) { 50 if (flag[i]) { 51 continue; 52 } 53 for (int j = 0; j < n; ++ j) { 54 if (i == j) continue; 55 else { 56 if (shoes[i].first <= shoes[j].first && shoes[i].second >= shoes[j].second) { 57 flag[i] = 1; 58 } 59 } 60 } 61 } 62 int cur = 0, ans = 1; 63 for (; cur < shoes.size() && flag[cur]; cur ++); 64 int last_end = shoes[cur].second, this_begin; 65 for (int i = cur + 1; i < shoes.size(); ++ i) { 66 if (flag[i]) continue; 67 this_begin = shoes[i].first; 68 if (last_end <= this_begin) { 69 ans ++; 70 last_end = shoes[i].second; 71 } 72 } 73 cout << ans << endl; 74 75 } 76 return 0; 77 }
2149 Problem D:
一道大数题目。在n个大数中寻找最小的数。大数推荐使用Java大数类,相对来说代码比较清晰。也可以直接开一个数组进行模拟。
1 import java.math.*; 2 import java.io.*; 3 import java.util.*; 4 5 public class Main { 6 public static void main(String args[]) { 7 Scanner in = new Scanner(System.in); 8 while (in.hasNext()) { 9 int n = in.nextInt(); 10 BigInteger ans = BigInteger.ZERO; 11 for (int i = 0; i < n; ++i) { 12 BigInteger a = in.nextBigInteger(); 13 if (i == 0) { 14 ans = a; 15 } else { 16 ans = ans.min(a); 17 } 18 } 19 System.out.println (ans); 20 } 21 } 22 }
2150 Problem E:
一道简单的数学题目。稍微推导一下就会发现这个函数最多只有六项。分别是a, b, b - a, -a, -b, a - b六个数,只要我们去一下重复的数即可。去重方法可以用一个字符串数组来做,这里用了set容器的性质进行了去重操作。
1 /****************************************/ 2 /***** Desgard_Duan *****/ 3 /****************************************/ 4 //#pragma comment(linker, "/STACK:102400000,102400000") 5 #define _CRT_SECURE_NO_WARNINGS 6 #include <iostream> 7 #include <cstdio> 8 #include <cstdlib> 9 #include <cstring> 10 #include <string> 11 #include <algorithm> 12 #include <stack> 13 #include <map> 14 #include <queue> 15 #include <vector> 16 #include <set> 17 #include <functional> 18 #include <cmath> 19 #include <numeric> 20 21 using namespace std; 22 23 inline void get_val(int &a) { 24 int value = 0, s = 1; 25 char c; 26 while ((c = getchar()) == ' ' || c == '\n'); 27 if (c == '-') s = -s; 28 else value = c - 48; 29 while ((c = getchar()) >= '0' && c <= '9') 30 value = value * 10 + c - 48; 31 a = s * value; 32 } 33 34 35 int a, b, n; 36 set<int> S; 37 int main () { 38 while (cin >> a >> b >> n) { 39 S.clear(); 40 if (n >= 6) { 41 S.insert (a); 42 S.insert (b); 43 S.insert (b - a); 44 S.insert (-a); 45 S.insert (-b); 46 S.insert (a - b); 47 cout << S.size() << endl; 48 continue; 49 } else { 50 int last = a, now = b, t; 51 S.insert (a); 52 S.insert (b); 53 for (int i = 3; i <= n; ++ i) { 54 S.insert (now - last); 55 t = now; 56 now = now - last; 57 last = t; 58 } 59 cout << S.size() << endl; 60 } 61 } 62 return 0; 63 }
最后,感谢这次的命题者:王浩宇(stdiohero),叶鹏(yeahpeng),王驰(wid),谢文亮(Dim),朱吴帅(JM)同学为我们出的这套热身题目。祝大家在参赛后有所提高。谢谢大家。
——Desgard_Duan
2014.10.31