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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

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 }
View Code

 

记一个脑残加手残选手数不清1e5有几个零不看样例就交题没想清楚就敲代码的日常。。

posted on 2016-08-04 20:58  HoneyCat  阅读(269)  评论(0编辑  收藏  举报

导航