1002 Hidden String
这个题怎么暴力怎么搞就好了. 可以枚举最长匹配前缀, 和最长匹配后缀, 中间暴力for.
1 /*Author :usedrose */ 2 /*Created Time :2015/7/25 19:05:28*/ 3 /*File Name :2.cpp*/ 4 #include <cstdio> 5 #include <iostream> 6 #include <algorithm> 7 #include <sstream> 8 #include <cstdlib> 9 #include <cstring> 10 #include <climits> 11 #include <vector> 12 #include <string> 13 #include <ctime> 14 #include <cmath> 15 #include <deque> 16 #include <queue> 17 #include <stack> 18 #include <set> 19 #include <map> 20 #define INF 0x3f3f3f3f 21 #define eps 1e-8 22 #define pi acos(-1.0) 23 #define MAXN 1110 24 #define OK cout << "ok" << endl; 25 #define o(a) cout << #a << " = " << a << endl 26 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 27 using namespace std; 28 typedef long long LL; 29 30 int T; 31 string s; 32 string t = "anniversary"; 33 34 int main() 35 { 36 37 cin >> T; 38 while (T--) { 39 cin >> s; 40 string a, b, c; 41 for (int i = 1;i < 11;++ i) 42 for (int j = 1;i + j < 11; ++ j) { 43 a = t.substr(0, i); 44 b = t.substr(i,j); 45 c = t.substr(i+j); 46 //cout << a << "!" << b << "!" << c << endl; 47 if (a == "" || b == "" || c == "") continue; 48 int pos1, pos2, pos3; 49 pos1 = s.find(a); 50 while (pos1 != -1) { 51 pos2 = s.find(b, pos1+ a.length()); 52 while (pos2 != -1) { 53 pos3 = s.find(c, pos2 +b.length()); 54 if (pos3 != -1) { 55 cout << "YES" << endl; 56 goto en; 57 } 58 pos2 = s.find(b, pos2 + 1); 59 if (pos2 == -1) break; 60 } 61 pos1 = s.find(a,pos1 + 1); 62 if (pos1 == -1) break; 63 } 64 } 65 cout << "NO" << endl; 66 en:; 67 } 68 return 0; 69 }
1003 Sequence
这个题看上去是一个贪心, 但是这个贪心显然是错的.
事实上这道题目很简单, 先判断1个是否可以, 然后判断2个是否可以. 之后找到最小的k(k>2), 使得(m−k)mod6=0即可.
证明如下:
3n(n−1)+1=6(n∗(n−1)/2)+1, 注意到n∗(n−1)/2是三角形数, 任意一个自然数最多只需要3个三角形数即可表示. 枚举需要k个, 那么显然m=6(k个三角形数的和)+k, 由于k≥3, 只要m−k是6的倍数就一定是有解的.
事实上, 打个表应该也能发现规律.
1 /*Author :usedrose */ 2 /*Created Time :2015/7/26 16:12:43*/ 3 /*File Name :2.cpp*/ 4 #include <cstdio> 5 #include <iostream> 6 #include <algorithm> 7 #include <sstream> 8 #include <cstdlib> 9 #include <cstring> 10 #include <climits> 11 #include <vector> 12 #include <string> 13 #include <ctime> 14 #include <cmath> 15 #include <deque> 16 #include <queue> 17 #include <stack> 18 #include <set> 19 #include <map> 20 #define INF 0x3f3f3f3f 21 #define eps 1e-8 22 #define pi acos(-1.0) 23 #define MAXN 20110 24 #define OK cout << "ok" << endl; 25 #define o(a) cout << #a << " = " << a << endl 26 #define o1(a,b) cout << #a << " = " << a << " " << #b << " = " << b << endl 27 using namespace std; 28 typedef long long LL; 29 30 31 int a[MAXN]; 32 int n, x; 33 34 void init() 35 { 36 for (int i = 1;i <= 20000; ++ i) 37 a[i] = 3*i*(i-1) + 1; 38 } 39 40 inline bool ok1(int x) 41 { 42 int pos = lower_bound(a, a + 2000, x) - a; 43 if (a[pos] == x) return 1; 44 return 0; 45 } 46 47 bool ok2(int x) 48 { 49 for(int i=1,j=20000; i < 20000 &&a[i] < x;i++){ 50 while(j > 0 && a[i] + a[j] > x){ 51 j--; 52 } 53 if(j > 0 && a[i]+a[j] == x){ 54 return true; 55 } 56 } 57 return false; 58 } 59 60 int main() 61 { 62 init(); 63 scanf("%d", &n); 64 while (n--) { 65 scanf("%d", &x); 66 if (ok1(x)) puts("1"); 67 else if (ok2(x)) puts("2"); 68 else { 69 for (int i = 3;i < 10; ++ i) 70 if ((x - i)% 6 == 0){ 71 printf("%d\n", i); 72 break; 73 } 74 } 75 } 76 return 0; 77 }
1004 Bipartite Graph
首先二分图可以分成两类点X和Y, 完全二分图的边数就是|X|⋅|Y|.我们的目的是max{|X|⋅|Y|}, 并且|X|+|Y|=n.
把原图黑白染色, 每个联通块有ai个黑点, bi个白点, 于是就是要确定ai属于X还是属于Y. 然后我们考虑dp, dpi,x表示用了前i个联通块, |X|=x是否可行. dp方程很容易确定, dpi,x=dpi−1,x−a[i] or dpi−1,x−b[i].
直接暴力是O(n2)的, 可以考虑用bitset优化, 这样就可以过了. 实际上由于数据很难造, 一些稍加优化的n2也可以过的
1005 Happy King
出题人的做法是点分治, 比赛的时候有人排序之后用lct维护单调性过了.
设分治中心为g, 我们只需要计算跨过g的答案, 其他的可以分治计算.
跨过根的可以容斥做, 没有限制的 - ∑端点落在同一颗子树上的. 上述两个过程是一样的, 于是只考虑没有限制的怎么做.
令xi,yi为i到g路径上的最大值和最小值. 我们按照xi排序, 然后枚举xi必选, 那么前面可选的xj,yj(j<i)必须要满足xi−d≤xj,xi−d≤yj, 由于xj≥yj, 只需要考虑xi−d≤yj. 于是只要枚举xi然后用树状数组统计答案即可. 复杂度是O(nlog2n).
事实上也是存在O(nlogn)的点分治做法, 分治时每次把树差不多分成两半, 就可以利用单调性, 用单调队列维护答案. 做法和POI2010 Pilots类似. 这个做法在比赛开始后Claris想到的.