2018年青岛站

 题目链接:http://acm.zju.edu.cn/onlinejudge/showContestProblems.do?contestId=381

C题:

题意:

  有长度为n的两个串s和t,你可以翻转两次子串(1->0,0->1),问有多种方案能使得s和t相等。

思路:

  1.对于初始时s==t有任取一个区间,将其翻转两次即可,此时方案数为n + n * (n - 1) / 2 = n * (n + 1) / 2;

  2.对于s和t有一个区间不同时,设这个区间为tt,则此时只需寻找一个大串ss包含tt,将ss串翻转一次,再将ss-tt翻转(顺序颠倒为另一方案)即可,设tt前面还有k1个字符,后面还有k2个字符,则此时方案数为(|tt| - 1)* 2 + 2 * k1 + 2 * k2;

  3.对于s和t有两个区间不同时,此时方案数固定为6:

    a.将第一个串翻转,第二个串翻转,顺序颠倒为另一种方案;

    b.第一个串及第一二个串中间的那段一起翻转,第二个串及第一二个串中间的那段一起翻转,顺序颠倒为另一种方案;

    c.第一个串及第一二个串中间那段以及第二个串进行翻转,将中间那段翻转,顺序颠倒为另一种方案。

  4.对于s和t不同的区间数大于2的,此时方案数为0。

代码实现如下:

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <stack>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <bitset>
 8 #include <cstdio>
 9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 using namespace std;
16 
17 typedef long long LL;
18 typedef pair<LL, LL> pLL;
19 typedef pair<LL, int> pli;
20 typedef pair<int, LL> pil;;
21 typedef pair<int, int> pii;
22 typedef unsigned long long uLL;
23 
24 #define lson rt<<1
25 #define rson rt<<1|1
26 #define lowbit(x) x&(-x)
27 #define  name2str(name) (#name)
28 #define bug printf("*********\n")
29 #define debug(x) cout<<#x"=["<<x<<"]" <<endl
30 #define FIN freopen("D://code//in.txt", "r", stdin)
31 #define IO ios::sync_with_stdio(false),cin.tie(0)
32 
33 const double eps = 1e-8;
34 const int mod = 1000000007;
35 const int maxn = 1e6 + 7;
36 const double pi = acos(-1);
37 const int inf = 0x3f3f3f3f;
38 const LL INF = 0x3f3f3f3f3f3f3f3fLL;
39 
40 int T, n;
41 char s[maxn], t[maxn];
42 pLL st[maxn];
43 
44 int main() {
45 #ifndef ONLINE_JUDGE
46     FIN;
47 #endif
48     scanf("%d", &T);
49     while(T--) {
50         scanf("%d", &n);
51         scanf("%s%s", s + 1, t + 1);
52         int cnt = 0, flag = 0;
53         for(int i = 1; i <= n; i++) {
54             if(s[i] != t[i] && !flag) {
55                 st[cnt].first = i;
56                 flag = 1;
57             } else if(s[i] == t[i] && flag) {
58                 st[cnt++].second = i;
59                 flag = 0;
60             }
61         }
62         if(flag) st[cnt++].second = n;
63         if(cnt == 0) printf("%lld\n", 1LL * n * (n + 1) / 2);
64         else if(cnt == 1) {
65             printf("%lld\n", 2 * (st[0].second - st[0].first) + 2 * (st[0].first - 1) + 2 * (n - st[0].second));
66         } else if(cnt == 2) {
67             printf("6\n");
68         } else {
69             printf("0\n");
70         }
71     }
72     return 0;
73 }

E题:

 

题意:

  题目背景为植物大战僵尸。

  你拥有n棵植物,每棵植物坐标为i(i=0,1,2……)的初始防御值均为0,成长值为ai。

  坐标0出有一辆浇水的车,该车只允许向左向右移动一格,移动到某个坐标i时就会对i上的植物进行浇水,使其防御值增长ai。

  花园的防御值的定义为所有植物的防御值的最小值。

  问花园的防御值的最大值为多少。

思路:

  一眼二分,二分花园的防御值为x,则该题等价于固定x,求使得所有植物的防御值di大于等于x的浇水车的最小移动步数。

  易知只有当这辆车在相邻两棵植物(x,x+1)间反复移动直至左边那颗植物的防御值大于等于x才转移到x+1与x+2间反复移动时浇水车的移动步数最优。

  不过对于最右端的n-1和n要特别分析,最后车子可以停留在n-1而不停留在n处。

代码实现如下:

  1 #include <set>
  2 #include <map>
  3 #include <queue>
  4 #include <stack>
  5 #include <cmath>
  6 #include <ctime>
  7 #include <bitset>
  8 #include <cstdio>
  9 #include <string>
 10 #include <vector>
 11 #include <cstdlib>
 12 #include <cstring>
 13 #include <iostream>
 14 #include <algorithm>
 15 using namespace std;
 16 
 17 typedef long long LL;
 18 typedef pair<LL, LL> pLL;
 19 typedef pair<LL, int> pli;
 20 typedef pair<int, LL> pil;;
 21 typedef pair<int, int> pii;
 22 typedef unsigned long long uLL;
 23 
 24 #define lson rt<<1
 25 #define rson rt<<1|1
 26 #define lowbit(x) x&(-x)
 27 #define  name2str(name) (#name)
 28 #define bug printf("*********\n")
 29 #define debug(x) cout<<#x"=["<<x<<"]" <<endl
 30 #define FIN freopen("D://code//in.txt", "r", stdin)
 31 #define IO ios::sync_with_stdio(false),cin.tie(0)
 32 
 33 const double eps = 1e-8;
 34 const int mod = 1000000007;
 35 const int maxn = 1e5 + 7;
 36 const double pi = acos(-1);
 37 const int inf = 0x3f3f3f3f;
 38 const LL INF = 0x3f3f3f3f3f3f3f3fLL;
 39 
 40 int t, n;
 41 LL m;
 42 int a[maxn];
 43 LL num[maxn];
 44 
 45 bool check(LL x) {
 46     for(int i = 1; i <= n; i++) {
 47         num[i] = (x + a[i] - 1) / a[i];
 48     }
 49     LL cnt = 0;
 50     for(int i = 1; i < n - 1; i++) {
 51         cnt ++;
 52         num[i]--;
 53         if(cnt > m) return false;
 54         if(num[i] > 0) {
 55             cnt += 2 * num[i];
 56             if(cnt > m) return false;
 57             if(num[i+1] > 0) {
 58                 num[i+1] -= num[i];
 59             }
 60             num[i] = 0;
 61         }
 62     }
 63     num[n-1]--;
 64     cnt++;
 65     if(num[n-1] > 0) {
 66         cnt += 2 * num[n-1];
 67         if(cnt > m) return false;
 68         num[n] -= num[n-1];
 69     }
 70     if(num[n] > 0) {
 71         num[n]--;
 72         cnt++;
 73         cnt += 2 * num[n];
 74     }
 75     return cnt <= m;
 76 }
 77 
 78 int main() {
 79 #ifndef ONLINE_JUDGE
 80     FIN;
 81 #endif
 82     scanf("%d", &t);
 83     while(t--) {
 84         scanf("%d%lld", &n, &m);
 85         for(int i = 1; i <= n;  i++) {
 86             scanf("%d",  &a[i]);
 87         }
 88         if(m < n) {
 89             printf("0\n");
 90             continue;
 91         }
 92         LL ub = INF, lb = 0, mid, ans;
 93         while(ub >= lb) {
 94             mid = (ub + lb) >> 1;
 95             if(check(mid)) {
 96                 ans = mid;
 97                 lb = mid + 1;
 98             } else {
 99                 ub = mid - 1;
100             }
101         }
102         printf("%lld\n", ans);
103     }
104     return 0;
105 }

J题:

题意:

  初始时主人公带着x元钱去书店买m本书,他的买书规则如下:

    1.书按照1至n排成一排进行编号;

    2.如果主人公身上目前拥有的钱大于等于书的价格则一定会买这本书,且主人公拥有的钱减少书的价格;

    3.如果主人公的钱少于书的价格则跳过该书。

  求主人公初始拥有的钱x的最大值(如果无法估计则输出Richhman,如果不能恰好购买m本书则输出Impossible)。

思路:

  对于本题由于买书规则的特殊,我们可以分析当n==m时此时主人公初始的钱是无法估计的,当书的价格为0的书的数量大于m时时Impossible。

  对于其他情况则需记录书的价格为0的书的数量,记为num,最后一本价格为0的书的位置为pos。

  1.如果pos<=m,则直接x=前m本书的价格+min(后面n-m本书的价格)- 1;

  2.如果pos>m,则购买m-num本非0的书,然后+min(其他非0书的价格) - 1。

代码实现如下:

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <stack>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <bitset>
 8 #include <cstdio>
 9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 using namespace std;
16 
17 typedef long long LL;
18 typedef pair<LL, LL> pLL;
19 typedef pair<LL, int> pli;
20 typedef pair<int, LL> pil;;
21 typedef pair<int, int> pii;
22 typedef unsigned long long uLL;
23 
24 #define lson rt<<1
25 #define rson rt<<1|1
26 #define lowbit(x) x&(-x)
27 #define  name2str(name) (#name)
28 #define bug printf("*********\n")
29 #define debug(x) cout<<#x"=["<<x<<"]" <<endl
30 #define FIN freopen("D://code//in.txt", "r", stdin)
31 #define IO ios::sync_with_stdio(false),cin.tie(0)
32 
33 const double eps = 1e-8;
34 const int mod = 1000000007;
35 const int maxn = 1e5 + 7;
36 const double pi = acos(-1);
37 const int inf = 0x3f3f3f3f;
38 const LL INF = 0x3f3f3f3f3f3f3f3fLL;
39 
40 int t, n, m;
41 int a[maxn];
42 
43 int main() {
44 #ifndef ONLINE_JUDGE
45     FIN;
46 #endif
47     scanf("%d", &t);
48     while(t--) {
49         scanf("%d%d", &n, &m);
50         int num = 0, pos = -1;
51         LL ans = 0;
52         int mx = inf, mx2 = inf;
53         for(int i = 0; i < n; i++) {
54             scanf("%d", &a[i]);
55             mx = min(mx, a[i]);
56             if(!a[i]) {
57                 num++;
58                 pos = i;
59             }
60             if(i < m) ans += a[i];
61             else {
62                 mx2 = min(mx2, a[i]);
63             }
64         }
65         if(n == m) {
66             printf("Richman\n");
67         } else {
68             if(num > m) {
69                 printf("Impossible\n");
70             } else {
71                 if(m == 0) {
72                     printf("%d\n", mx - 1);
73                 } else {
74                     if(pos >= m) {
75                         m -= num;
76                         int tmp = 0;
77                         mx2 = inf, ans = 0;
78                         for(int i = 0; i < n; i++) {
79                             if(a[i] && tmp < m) {
80                                 ans += a[i];
81                                 tmp++;
82                             } else if(a[i]) {
83                                 mx2 = min(mx2, a[i]);
84                             }
85                         }
86                     }
87                     printf("%lld\n", ans + mx2 - 1);
88                 }
89             }
90         }
91     }
92     return 0;
93 }

 M题:

题意:

  给你每个数对应的权值。

  定义f(x)=x的每一位上的数字对应的权值之和。

  定义g[0][x]=x,g[k][x]=f(g[k-1][x]),k>=1。

  求g[k][x]。

思路:

  经冷静分析我们可以发现当k大于等于2(打表可以发现,不过由于我只打了前几千的值,可能这个数应该要大于2,但是绝对非常小)时其实就是0和1的循环,因此我们对于前面的值进行暴力,出现0时就直接break掉,并记录此时对应的是第多少位上(记为pos),如果k<=pos,那么就直接输出,否则如果k%2==pos%2,则输出0,否则输出1。

代码实现如下:

 1 #include <set>
 2 #include <map>
 3 #include <queue>
 4 #include <stack>
 5 #include <cmath>
 6 #include <ctime>
 7 #include <bitset>
 8 #include <cstdio>
 9 #include <string>
10 #include <vector>
11 #include <cstdlib>
12 #include <cstring>
13 #include <iostream>
14 #include <algorithm>
15 using namespace std;
16 
17 typedef long long LL;
18 typedef pair<LL, LL> pLL;
19 typedef pair<LL, int> pli;
20 typedef pair<int, LL> pil;;
21 typedef pair<int, int> pii;
22 typedef unsigned long long uLL;
23 
24 #define lson rt<<1
25 #define rson rt<<1|1
26 #define lowbit(x) x&(-x)
27 #define  name2str(name) (#name)
28 #define bug printf("*********\n")
29 #define debug(x) cout<<#x"=["<<x<<"]" <<endl
30 #define FIN freopen("D://code//in.txt", "r", stdin)
31 #define IO ios::sync_with_stdio(false),cin.tie(0)
32 
33 const double eps = 1e-8;
34 const int mod = 1000000007;
35 const int maxn = 30000000 + 7;
36 const double pi = acos(-1);
37 const int inf = 0x3f3f3f3f;
38 const LL INF = 0x3f3f3f3f3f3f3f3fLL;
39 
40 int t, x, k;
41 int a[20], num[] = {1, 0, 0, 0, 1, 0, 1, 0, 2, 1};
42 
43 int main() {
44     scanf("%d", &t);
45     while(t--) {
46         scanf("%d%d", &x, &k);
47         if(k == 0) {
48             printf("%d\n", x);
49             continue;
50         }
51         int pos = -1, cnt = 0;
52         if(x == 0) a[cnt++] = 0;
53         while(x) {
54             a[cnt++] = x % 10;
55             x /= 10;
56         }
57         for(int i = 1; i <= k; i++) {
58             x = 0;
59             for(int i = 0; i < cnt; i++) {
60                 x += num[a[i]];
61             }
62             //debug(x);
63             if(x == 0) {
64                 pos = i;
65                 break;
66             } else if(i == k) {
67                 printf("%d\n", x);
68             }
69             cnt = 0;
70             while(x) {
71                 a[cnt++] = x % 10;
72                 x /= 10;
73             }
74         }
75         //debug(pos);
76         if(pos != -1) {
77             if(k % 2 == pos % 2) {
78                 printf("0\n");
79             } else {
80                 printf("1\n");
81             }
82         }
83     }
84     return 0;
85 }

 

posted @ 2018-11-05 17:31  Dillonh  阅读(161)  评论(0编辑  收藏  举报