codeforces #106 div2 && Weak Win弱鸡赢第三场
这一场难度还算。。适中?
窝太弱啦!小伙伴们都在div1混迹若干年了我还在纠结div2……
A. Business trip 大概就是知道这个人每个月浇花的话花生长的长度ai,一年的生长总量要达到k厘米,问最少的浇花月份数。
好多场cf开篇都是这么一道排序+贪心?
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <queue> 5 #include <string> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 typedef long long LL; 10 const int mod = 1e9+7; 11 const int maxn=100005; 12 int a[15],k; 13 int main(){ 14 scanf("%d",&k); 15 for (int i=0; i<12; i++) { 16 scanf("%d", &a[i]); 17 } 18 sort(a, a + 12); 19 int cnt = 0, sum = 0; 20 for (int i=11; i>=0; i--) { 21 if (sum >= k) { 22 break; 23 } 24 sum += a[i], cnt++; 25 } 26 if (sum < k) { 27 puts("-1"); 28 } else { 29 printf("%d\n", cnt); 30 } 31 return 0; 32 }
B. Martian Clock 火星上的时间和地球相似,都是一天24小时一小时60分钟,但是不知道发过来的时间的进制数。求所有可能的进制数,无限输出-1,不可能输出0.
简单判断一下,肯定是当前最大的数字+1为最小的可能的进制数,然后往上算就好啦。超出了24小时60分钟就是判断不合法的条件。无限怎么判呢,这里有一个进制数上限是60,想一想就知道啦。如果分钟数给一个1的话,最大就是59进制。
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <queue> 5 #include <string> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 typedef long long LL; 10 const int mod = 1e9+7; 11 const int maxn=100005; 12 char s[55], a[55], b[55]; 13 int am = 0, bm = 0, sa = 0, sb = 0; 14 int conv(char c) { 15 if (c>='0' && c<='9') 16 return c-'0'; 17 else 18 return c-'A'+10; 19 } 20 int calc(char s[], int t) { 21 int ret = 0; 22 for (int i=0; s[i]; i++) { 23 ret = ret * t + conv(s[i]); 24 } 25 return ret; 26 } 27 int main(){ 28 scanf("%s", s); 29 int flag = 0, l1 = 0, l2 = 0, ff = 1, t; 30 for (int i=0; s[i]; i++) { 31 if (!flag) { 32 if (s[i] != ':') { 33 if (ff && s[i] == '0') { 34 continue; 35 } 36 ff = 0; 37 a[l1++] = s[i]; 38 t = conv(s[i]); 39 am = max(am, t); 40 } else { 41 flag = 1; 42 ff = 1; 43 } 44 } else { 45 if (ff && s[i] == '0') { 46 continue; 47 } 48 ff = 0; 49 b[l2++] = s[i]; 50 t = conv(s[i]); 51 bm = max(bm, t); 52 } 53 } 54 for (int i=max(am, bm)+1; ; i++) { 55 sa = calc(a, i), sb = calc(b, i); 56 if (sa > 23 || sb > 59) { 57 if (i == max(am, bm)+1) { 58 puts("0"); 59 return 0; 60 } 61 t = i; 62 break; 63 } 64 if (i > 60) { 65 puts("-1"); 66 return 0; 67 } 68 } 69 for (int i=max(am, bm)+1; i<t; i++) { 70 printf("%d ",i); 71 } 72 return 0; 73 }
C. Division into Teams 有n个人,每个人的技能等级是ai,现在要把这些人划成2队,要求每个人都有队,两队人数最多相差1,两队技能等级和最多相差最大的ai。
奇怪的构造。排个序,两两一组维护一下两队的等级差,哪个等级和比较大就把小的那个人分配给它。这样下来差永远不可能大于max{ai}。
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <queue> 5 #include <string> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 typedef long long LL; 10 const int mod = 1e9+7; 11 const int maxn=100005; 12 struct node { 13 int val, i; 14 bool operator<(const node &rhs)const { 15 return val > rhs.val; 16 } 17 } a[maxn]; 18 int n,a1[maxn],a2[maxn],flag,c1=0,c2=0; 19 int main(){ 20 scanf("%d",&n); 21 int dif = 0; 22 for (int i=1; i<=n; i++) { 23 scanf("%d",&a[i].val); 24 a[i].i = i; 25 } 26 sort(a + 1, a + n + 1); 27 //for(int i=1;i<=n;i++)printf("=%d,%d=",a[i].val,a[i].i);puts(""); 28 if (n & 1) { 29 flag = 1; 30 n--; 31 } 32 for (int i=1; i<=n; i+=2) { 33 if (dif > 0) { 34 a1[++c1] = a[i+1].i, a2[++c2] = a[i].i; 35 dif -= a[i].val - a[i+1].val; 36 } else { 37 a2[++c2] = a[i+1].i, a1[++c1] = a[i].i; 38 dif += a[i].val - a[i+1].val; 39 } 40 } 41 if (flag) { 42 if (dif > 0) { 43 a2[++c2] = a[n+1].i; 44 } else { 45 a1[++c1] = a[n+1].i; 46 } 47 } 48 printf("%d\n", c1); 49 for (int i=1; i<=c1; i++) { 50 printf("%d%c",a1[i],i==c1?'\n':' '); 51 } 52 printf("%d\n", c2); 53 for (int i=1; i<=c2; i++) { 54 printf("%d%c",a2[i],i==c2?'\n':' '); 55 } 56 return 0; 57 }
D. Coloring Brackets 有一堆括号形如(()()),保证都能配对,现在要给它们染色,染色规则如下:每个括号要么不染色,要么染成红色或蓝色;每一对括号要么左边染色,要么右边染色;两个相邻的括号不能同色。求合法方案数。
dp+dfs。分两种状态讨论:如果当前搜索的l,r正好匹配,那么直接往中间搜处理结果;否则找出和左边括号匹配的点,左段右段分别搜出来然后再处理结果。返回条件是当前只剩下(),单组括号有4种合法方案。
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <queue> 5 #include <stack> 6 #include <string> 7 #include <iostream> 8 #include <algorithm> 9 using namespace std; 10 typedef long long LL; 11 const int mod = 1e9+7; 12 const int maxn=100005; 13 char s[777]; 14 int f[777][777][3][3], match[777]; 15 stack<int> stk; 16 void dp(int l, int r) { 17 if (l == r - 1) { 18 f[l][r][0][1] = f[l][r][0][2] = f[l][r][1][0] = f[l][r][2][0] = 1; 19 return; 20 } 21 if (match[l] == r) { 22 dp(l+1, r-1); 23 for (int i=0; i<3; i++) 24 for (int j=0; j<3; j++) { 25 if (j != 1) 26 f[l][r][0][1] = (f[l][r][0][1] + f[l+1][r-1][i][j]) % mod; 27 if (i != 1) 28 f[l][r][1][0] = (f[l][r][1][0] + f[l+1][r-1][i][j]) % mod; 29 if (j != 2) 30 f[l][r][0][2] = (f[l][r][0][2] + f[l+1][r-1][i][j]) % mod; 31 if (i != 2) 32 f[l][r][2][0] = (f[l][r][2][0] + f[l+1][r-1][i][j]) % mod; 33 } 34 } else { 35 dp(l, match[l]); dp(match[l]+1, r); 36 for (int i=0; i<3; i++) 37 for (int j=0; j<3; j++) 38 for (int x=0; x<3; x++) 39 for (int y=0; y<3; y++) 40 if (!((x==1&&y==1) || (x==2&&y==2))) { 41 (f[l][r][i][j] += (1LL * f[l][match[l]][i][x] * f[match[l]+1][r][y][j]) % mod) %= mod; 42 } 43 } 44 } 45 int main(){ 46 scanf("%s", s + 1); 47 int len = strlen(s + 1); 48 for (int i=len; i>0; i--) { 49 if (s[i] == ')') { 50 stk.push(i); 51 } else { 52 match[i] = stk.top(); stk.pop(); 53 } 54 } 55 dp(1, len); 56 int ans = 0; 57 for (int i=0; i<3; i++) { 58 for (int j=0; j<3; j++) { 59 (ans += f[1][len][i][j]) %= mod; 60 } 61 } 62 printf("%d\n", ans); 63 return 0; 64 }
E. Martian Strings 有一个字符串s,从里面选择性的挑s[a,b],s[c,d]阅读(1 ≤ a ≤ b < c ≤ d ≤ n),先读前面的再读后面的,现在给你一个美丽词汇的列表,问在这两段之间(一个词可以分在左边一部分和右边一部分)最多能看见多少种这样的词。
众所周知kmp是专门处理字符串匹配的。这个题要求一个词拆成两部分,那么正着匹一遍当前缀,倒着匹一遍当后缀,两边捏巴捏巴能捏起来的就满足题意。注意对长度为1的词的特判。
1 #include <stdio.h> 2 #include <string.h> 3 #include <vector> 4 #include <queue> 5 #include <string> 6 #include <iostream> 7 #include <algorithm> 8 using namespace std; 9 typedef long long LL; 10 const int mod = 1e9+7; 11 const int maxn=100005; 12 char t[maxn], p[maxn], tr[maxn], pr[maxn]; 13 int f[maxn], d[2][maxn], flag; 14 void getFail(char* P, int* f) { 15 int m = strlen(P); 16 f[0] = 0; 17 f[1] = 0; 18 for (int i=1; i<m; i++) { 19 int j = f[i]; 20 while (j && P[i] != P[j]) { 21 j = f[j]; 22 } 23 f[i+1] = P[i]==P[j] ? j+1 : 0; 24 } 25 } 26 void find(char* T, char*P, int*f) { 27 int n = strlen(T), m = strlen(P); 28 getFail(P, f); 29 int j = 0; 30 for (int i=0; i<n; i++) { 31 while (j && P[j] != T[i]) { 32 j = f[j]; 33 } 34 if (P[j] == T[i]) { 35 j++; 36 } 37 if (i) { 38 d[flag][i] = max(j, d[flag][i-1]); 39 } else { 40 d[flag][i] = j; 41 } 42 } 43 } 44 int main(){ 45 scanf("%s", t); 46 int n = strlen(t), q, ans = 0; 47 strcpy(tr, t); reverse(tr, tr + n); 48 scanf("%d", &q); 49 while (q--) { 50 scanf("%s", p); 51 int m = strlen(p); 52 if (m == 1) { 53 continue; 54 } 55 strcpy(pr, p); reverse(pr, pr + m); 56 flag = 0; getFail(p, f); find(t, p, f); 57 flag = 1; getFail(pr, f); find(tr, pr, f); 58 for (int i=0; i<n; i++) { 59 if (n-i-2 < 0) { 60 break; 61 } 62 if (d[0][i] + d[1][n-i-2] >= m) { 63 ans++; 64 break; 65 } 66 } 67 } 68 printf("%d\n", ans); 69 return 0; 70 }
记一个脑残加手残选手数不清1e5有几个零不看样例就交题没想清楚就敲代码的日常。。