「美团 CodeM 资格赛」试题泛做

Posted cot

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了「美团 CodeM 资格赛」试题泛做相关的知识,希望对你有一定的参考价值。

LibreOJ真是吼啊!

数码

推个式子,把枚举因数转为枚举倍数。然后就发现它是根号分段的。然后每一段算一下就好了。

技术分享
 1 #include <cstdio>
 2 #include <cstring>
 3 
 4 #define R register
 5 typedef long long ll;
 6 struct Data {
 7     ll num[10];
 8     inline void clear()
 9     {
10         memset(num, 0, 10 << 3);
11     }
12     inline Data operator + (const Data &that) const
13     {
14         R Data ret; memcpy(ret.num, num, 10 << 3);
15         for (R int i = 1; i <= 9; ++i) ret.num[i] += that.num[i];
16         return ret;
17     }
18     inline void operator += (const Data &that)
19     {
20         for (R int i = 1; i <= 9; ++i) num[i] += that.num[i];
21     }
22     inline Data operator - (const Data &that) const
23     {
24         R Data ret; memcpy(ret.num, num, 10 << 3);
25         for (R int i = 1; i <= 9; ++i) ret.num[i] -= that.num[i];
26         return ret;
27     }
28     inline void operator *= (const int &that)
29     {
30         for (R int i = 1; i <= 9; ++i) num[i] *= that;
31     }
32 } ;
33 inline Data calc2(R int N)
34 {
35     R ll tmp; R Data ret; ret.clear();
36     for (tmp = 10; tmp - 1 <= N; tmp *= 10)
37         for (R int i = 1; i <= 9; ++i)
38             ret.num[i] += tmp / 10;
39     tmp /= 10;
40     for (R int i = 1; i < (N / tmp); ++i) ret.num[i] += tmp;
41     ret.num[N / tmp] += N % tmp + 1;
42 //    printf("calc2(%d) = \n", N);
43 //    for (R int i = 1; i <= 9; ++i) printf("%lld\n", ret.num[i]);
44     return ret;
45 }
46 inline Data calc(R int N)
47 {
48     R Data ret; ret.clear();
49     for (R int i = 1, j; i <= N; i = j + 1)
50     {
51         j = N / (N / i);
52         R Data tmp = calc2(j) - calc2(i - 1);
53         tmp *= N / i;
54         ret += tmp;
55     }
56     return ret;
57 }
58 int main()
59 {
60     R int l, r; scanf("%d%d", &l, &r);
61     R Data ans = calc(r) - calc(l - 1);
62     for (R int i = 1; i <= 9; ++i)
63         printf("%lld\n", ans.num[i]);
64     return 0;
65 }
数码

跳格子

预处理出每个点能不能到终点。然后直接暴搜就好了。

技术分享
 1 #include <cstdio>
 2 #include <cstdlib>
 3 
 4 #define R register
 5 #define maxn 100010
 6 struct Edge {
 7     Edge *next;
 8     int to;
 9 } *last[maxn], e[maxn << 1], *ecnt = e;
10 inline void link(R int a, R int b)
11 {
12     *++ecnt = (Edge) {last[a], b}; last[a] = ecnt;
13 }
14 int q[maxn], n, a[maxn], b[maxn];
15 bool arv[maxn], ins[maxn];
16 char st[maxn];
17 void dfs(R int x, R int step)
18 {
19     if (!arv[x]) return ;
20     if (x == n)
21     {
22         for (R int i = 1; i < step; ++i) printf("%c", st[i]); puts("");
23         exit(0);
24     }
25     if (ins[x])
26     {
27         puts("Infinity!");
28         exit(0);
29     }
30     ins[x] = 1;
31     if (x + a[x] > 0 && x + a[x] <= n)
32     {
33         st[step] = a;
34         dfs(x + a[x], step + 1);
35     }
36     if (x + b[x] > 0 && x + b[x] <= n)
37     {
38         st[step] = b;
39         dfs(x + b[x], step + 1);
40     }
41 }
42 int main()
43 {
44     scanf("%d", &n);
45     for (R int i = 1; i <= n; ++i) scanf("%d", a + i), i + a[i] > 0 && i + a[i] <= n ? link(i + a[i], i), 1 : 0;
46     for (R int i = 1; i <= n; ++i) scanf("%d", b + i), i + b[i] > 0 && i + b[i] <= n ? link(i + b[i], i), 1 : 0;
47     R int head = 0, tail = 1; arv[q[1] = n] = 1;
48     while (head < tail)
49     {
50         R int now = q[++head];
51         for (R Edge *iter = last[now]; iter; iter = iter -> next)
52             if (!arv[iter -> to]) arv[q[++tail] = iter -> to] = 1;
53     }
54     if (!arv[1]) {puts("No solution!"); return 0;}
55     dfs(1, 1);
56     return 0;
57 }
跳格子

优惠券

一开始傻逼了,以为只要前缀就好了,后来才发现是区间。。。对于每个不满足的条件的左/右括号扔进一个数据结构里,然后每次遇到问号的时候,去消右端点最近的一个括号。然后这个数据结构用堆就够啦~

技术分享
 1 #include <cstdio>
 2 #include <vector>
 3 #include <queue>
 4 
 5 #define R register
 6 #define maxn 500010
 7 int last[maxn], lastt[maxn];
 8 struct Opt {int type, x;} p[maxn];
 9 std::vector<int> v[maxn];
10 std::priority_queue<int, std::vector<int>, std::greater<int> > q;
11 int main()
12 {
13     R int n, num = 0; scanf("%d", &n);
14     for (R int i = 1; i <= n; ++i)
15     {
16         char opt[3]; scanf("%s", opt);
17         if (opt[0] == I)
18         {
19             R int x; scanf("%d", &x);
20             p[i] = (Opt) {1, x};
21         }
22         if (opt[0] == O)
23         {
24             R int x; scanf("%d", &x);
25             p[i] = (Opt) {0, x};
26         }
27         if (opt[0] == ?) p[i] = (Opt) {2, 0};
28     }
29     for (R int i = 1; i <= n; ++i)
30     {
31         if (p[i].type == 2) continue;
32         if (lastt[p[i].x] == p[i].type)
33         {
34             v[last[p[i].x]].push_back(i);
35         }
36         last[p[i].x] = i;
37         lastt[p[i].x] = p[i].type;
38     }
39     for (R int i = 0; i < v[0].size(); ++i) q.push(v[0][i]);
40     for (R int i = 1; i <= n; ++i)
41     {
42         for (R int j = 0; j < v[i].size(); ++j) q.push(v[i][j]);
43         if (p[i].type == 2 && !q.empty())
44         {
45             R int top = q.top(); q.pop();
46             if (top < i) return !printf("%d\n", top);
47         }
48     }
49     if (q.empty()) puts("-1");
50     else printf("%d\n", q.top());
51     return 0;
52 }
优惠劵

 

以上是关于「美团 CodeM 资格赛」试题泛做的主要内容,如果未能解决你的问题,请参考以下文章

CodeM美团点评编程竞赛资格赛题

美团CodeM资格赛第二题

「美团 CodeM 资格赛」跳格子

CodeM 2017美团点评编程大赛资格赛

#6085. 「美团 CodeM 资格赛」优惠券

LibreOJ 6048 美团 CodeM 资格赛 跳格子