"字节跳动杯"2018中国大学生程序设计竞赛-女生专场 Solution

A - 口算训练

题意:询问 $[L, R]$区间内 的所有数的乘积是否是D的倍数

思路:考虑分解质因数

显然,一个数$x > \sqrt{x} 的质因子只有一个$

那么我们考虑将小于$\sqrt {x}$ 的质因子用线段树维护

其他质因子用vector 维护存在性

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 100010
  5 #define block 317 
  6 vector <int> fac[N], bigfac[10010];
  7 int t, n, q;
  8 int arr[N], pos[N], cnt; 
  9 
 10 void init()
 11 {
 12     cnt = 0;
 13     memset(pos, 0, sizeof pos);
 14     for (int i = 2; i < N; ++i)
 15     {
 16         if (pos[i] || i > block) continue;
 17         for (int j = i * i; j < N; j += i)
 18             pos[j] = 1; 
 19     }
 20     for (int i = 2; i < N; ++i) if (!pos[i]) pos[i] = ++cnt;
 21     for (int i = 2; i <= 100000; ++i)
 22     {
 23         int n = i;
 24         for (int j = 2; j * j <= n; ++j)
 25         {
 26             while (n % j == 0)
 27             {
 28                 n = n / j;
 29                 fac[i].push_back(j);  
 30             }
 31         }
 32         if (n != 1) fac[i].push_back(n);
 33         sort(fac[i].begin(), fac[i].end());
 34     }
 35 }
 36 
 37 int T[80]; 
 38 struct SEG
 39 {
 40     #define M N * 300
 41     int a[M], lson[M], rson[M], cnt;
 42        void init() { cnt = 0; }
 43     void pushup(int id) { a[id] = a[lson[id]] + a[rson[id]]; }
 44     void update(int &id, int l, int r, int pos)
 45     { 
 46         if (!id) 
 47         {
 48             id = ++cnt;
 49             a[id] = lson[id] = rson[id] = 0;
 50         }
 51         if (l == r) 
 52         {
 53             ++a[id]; 
 54             return;
 55         }
 56         int mid = (l + r) >> 1;
 57         if (pos <= mid) update(lson[id], l, mid, pos);
 58         else update(rson[id], mid + 1, r, pos);
 59         pushup(id);
 60     }
 61     int query(int id, int l, int r, int ql, int qr)
 62     {
 63         if (!id) return 0;
 64         if (l >= ql && r <= qr) return a[id];
 65         int mid = (l + r) >> 1;
 66         int res = 0;
 67         if (ql <= mid) res += query(lson[id], l, mid, ql, qr);
 68         if (qr > mid) res += query(rson[id], mid + 1, r, ql, qr);
 69         return res;
 70     }
 71 }seg;
 72 
 73 bool Get(int base, int need, int l, int r)
 74 {
 75 //    printf("%d %d %d %d\n", base, need, l, r);
 76     int have = 0;
 77     if (base < block)
 78     {
 79         have = seg.query(T[pos[base]], 1, n, l, r);
 80         if (have < need) return false;
 81     }
 82     else
 83     {
 84         have = upper_bound(bigfac[pos[base]].begin(), bigfac[pos[base]].end(), r) - lower_bound(bigfac[pos[base]].begin(), bigfac[pos[base]].end(), l);
 85         if (have < need) return false;
 86     }
 87     return true; 
 88 }
 89 
 90 bool work(int l, int r, int d)
 91 {
 92     if (d == 1) return true; 
 93     int base = fac[d][0], need = 1, have = 0;
 94     for (int i = 1, len = fac[d].size(); i < len; ++i)
 95     {
 96         if (fac[d][i] != base) 
 97         {
 98             if (Get(base, need, l, r) == false) return false;
 99             base = fac[d][i];
100             need = 1;  
101         }
102         else ++need;
103     }
104     return Get(base, need, l, r);
105 }
106 
107 int main()
108 {
109     init();
110     scanf("%d", &t);
111     while (t--)
112     {
113         scanf("%d%d", &n, &q);
114         for (int i = 1; i < 10010; ++i) bigfac[i].clear(); 
115         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
116         seg.init(); memset(T, 0, sizeof T); 
117         for (int i = 1; i <= n; ++i)
118         {
119             for (auto it : fac[arr[i]])
120             {
121                 if (it < block)
122                     seg.update(T[pos[it]], 1, n, i);                                    
123                 else
124                     bigfac[pos[it]].push_back(i);
125             }
126         }    
127         for (int i = 1; i <= cnt; ++i) sort(bigfac[i].begin(), bigfac[i].end());
128         for (int i = 1, l, r, d; i <= q; ++i)
129         {
130             scanf("%d%d%d", &l, &r, &d);
131             puts(work(l, r, d) ? "Yes" : "No");
132         }
133     }
134     return 0;
135 }
View Code

 

B - 缺失的数据范围

题意:给出$a, b, k$ 求一个最大的n 使得 $n^{a} \cdot log ^b n <= k$ 

思路:二分  但是要注意用高精度,求log的时候 平方逼近

 1 import java.io.BufferedInputStream;
 2 import java.util.Scanner;
 3 import java.math.*;
 4 
 5 public class Main {
 6 
 7     public static BigInteger Get(BigInteger x, int a, int b)
 8     {
 9         BigInteger two = BigInteger.valueOf(2);
10         BigInteger tmp = BigInteger.ONE;
11         BigInteger cnt = BigInteger.ZERO;
12         while (tmp.compareTo(x) < 0)
13         {
14             tmp = tmp.multiply(two);
15             cnt = cnt.add(BigInteger.ONE);
16         }
17         BigInteger res = x.pow(a).multiply(cnt.pow(b));
18         return res;
19     }
20 
21 
22     public static void main(String[] args) {
23         Scanner in = new Scanner(new BufferedInputStream(System.in));
24         int t = in.nextInt();
25         int a, b; BigInteger k, l, r, mid, ans, zero, two, one;
26         zero = BigInteger.ZERO;
27         two = BigInteger.valueOf(2);
28         one = BigInteger.valueOf(1);
29         while (t-- != 0)
30         {
31             a = in.nextInt();
32             b = in.nextInt();
33             k = in.nextBigInteger();
34             l = one;
35             r = k;
36             ans = zero;
37             while (r.subtract(l).compareTo(zero) >= 0)
38             {
39                 mid = l.add(r).divide(two);
40                 if (Get(mid, a, b).compareTo(k) <= 0)
41                 {
42                     ans = mid;
43                     l = mid.add(one);
44                 }
45                 else
46                     r = mid.subtract(one);
47             }
48             System.out.println(ans);
49         }
50         in.close();
51     }
52 }
View Code

 

C - 寻宝游戏

留坑。

 

D - 奢侈的旅行
题意:经过一条路的花费为$log_2^{\frac {level + a_i}{level}}$ 并且 $cost < b_i$ 时不能经过这条路,求$1 -> n$ 的最短路径

思路:考虑等式两边取2的幂次  比如

考虑 $log_2^a + log_2^b = log_2^{ab}$

那么 cost 为

$log_2^{\frac{1 + a_1}{a_1}} + log_2^{\frac {1 + a_1 + a_2}{1 + a_1}} + log_2^{\frac{1 + a_1 + a_2 + a_k}{1 + a_1 + a_2}}$

等价于

$log_2^{1 + a_1 + a_2 + a_k}$

再取2的幂次

$2^{cost} = 2^{log_2 ^{1 + a_1 + a_2 + a_k}}$

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define ll long long
 5 #define INFLL 0x3f3f3f3f3f3f3f3f
 6 #define N 100010
 7 int t, n, m;
 8 struct Edge { int to; ll a, b; };
 9 vector <Edge> G[N];
10 
11 struct dnode
12 {
13     int u; ll w;
14     dnode () {}
15     dnode (int u, ll w) : u(u), w(w) {}
16     bool operator < (const dnode &r) const { return w > r.w; }
17 };
18 
19 ll dist[N]; bool used[N];
20 void Dijkstra()
21 {
22     for (int i = 1; i <= n; ++i) dist[i] = INFLL, used[i] = 0;
23     priority_queue <dnode> q; q.emplace(1, 1); dist[1] = 1;
24     while (!q.empty())
25     {
26         int u = q.top().u; q.pop();
27         if (used[u]) continue;
28         used[u] = 1;
29         for (auto it : G[u]) 
30         {
31             int v = it.to; ll a = it.a, b = it.b;
32             if (!used[v] && dist[v] > dist[u] + a && a / dist[u] >= b - 1)
33             {
34                 dist[v] = dist[u] + a;
35                 q.emplace(v, dist[v]);
36             }
37             
38         }
39     }
40 }
41 
42 int main()
43 {
44     scanf("%d", &t);
45     while (t--)
46     {
47         scanf("%d%d", &n, &m);
48         for (int i = 1; i <= n; ++i) G[i].clear();
49         for (int i = 1, u, v, a, b; i <= m; ++i)
50         {
51             scanf("%d%d%d%d", &u, &v, &a, &b);
52             G[u].push_back(Edge{ v, a, 1ll << b});  
53         }
54         Dijkstra();
55         if (dist[n] == INFLL) puts("-1");
56         else printf("%lld\n", (ll)(log2(dist[n])));
57         
58     }
59     return 0;
60 }
View Code

 

E - 对称数

题意:找树上一条路径中最小的出现次数为偶数的数

思路:树分块+数字分块   找数字的时候分块统计 $O(1)$更新

好像卡了树上路径莫队。

  1 #include <bits/stdc++.h>
  2 using namespace std;
  3 
  4 #define N 200010
  5 #define block 450
  6 #define INF 0x3f3f3f3f
  7 int t, n, m;
  8 int arr[N];
  9 vector <int> G[N];  
 10 int deep[N], fa[N], top[N], son[N], sze[N], cnt; 
 11 int szeblock[N], Belong[N], dfn[N], dfscnt, dfssize; 
 12 stack <int> sta;
 13 
 14 void DFS(int u)
 15 {
 16     dfn[u] = ++dfscnt;
 17     sta.push(u);    
 18     szeblock[u] = 0; 
 19     sze[u] = 1;
 20     for (auto v : G[u]) if (v != fa[u]) 
 21     {
 22         fa[v] = u;
 23         deep[v] = deep[u] + 1;
 24         DFS(v); sze[u] += sze[v]; szeblock[u] += szeblock[v];
 25         if (son[u] == -1 || sze[v] > sze[son[u]]) son[u] = v;
 26         if (szeblock[u] >= block)
 27         {
 28             szeblock[u] = 0;
 29             ++dfssize; 
 30             while (!sta.empty() && sta.top() != u) { Belong[sta.top()] = dfssize; sta.pop(); }
 31         }
 32     }
 33     ++szeblock[u];
 34 }
 35 
 36 void getpos(int u, int sp)
 37 {
 38     top[u] = sp;
 39     if (son[u] == -1) return;
 40     getpos(son[u], sp);
 41     for (auto v : G[u]) if (v != son[u] && v != fa[u])
 42         getpos(v, v);
 43 }
 44 
 45 int querylca(int u, int v)
 46 {
 47     int fu = top[u], fv = top[v];
 48     while (fu != fv)
 49     {
 50         if (deep[fu] < deep[fv])
 51         {
 52             swap(fu, fv);
 53             swap(u, v);
 54         }
 55         u = fa[fu]; fu = top[u];
 56     }
 57     if (deep[u] > deep[v]) swap(u, v);
 58     return u;
 59 }
 60 
 61 struct qnode 
 62 {
 63     int u, v, id, lca;
 64     qnode() {}
 65     qnode(int u, int v, int id, int lca) : u(u), v(v), id(id), lca(lca) {}
 66     bool operator < (const qnode &r) const
 67     {
 68         return Belong[u] == Belong[r.u] ? dfn[v] < dfn[r.v] : Belong[u] < Belong[r.u];
 69     }
 70 }que[N]; int ans[N];  
 71 
 72 int used[N], cnt_num[N], num_block[block];
 73 void work(int x)
 74 {
 75     if (used[x]) --cnt_num[arr[x]];
 76     else ++cnt_num[arr[x]]; 
 77     num_block[(arr[x] - 1) / block] += 1 * ((cnt_num[arr[x]] & 1) ? 1 : -1);
 78     used[x] ^= 1;
 79 }
 80 
 81 void update(int u, int v)
 82 {
 83     while (u != v)
 84     {
 85         if (deep[u] > deep[v]) swap(u, v);
 86         work(v);
 87         v = fa[v];
 88     }
 89 }
 90 
 91 int Get()
 92 {
 93     for (int k = 0; k < block; ++k) if (num_block[k] != block)
 94     {
 95         int l = k * block + 1, r = (k + 1) * block;
 96         for (int j = l; j <= r; ++j) if (cnt_num[j] % 2 == 0)
 97             return j;
 98     }
 99 }
100 
101 int main()
102 {
103     scanf("%d", &t);
104     while (t--)
105     {
106         scanf("%d%d", &n, &m);
107         memset(son, -1, sizeof son);
108         cnt = 0; dfssize = 0; dfscnt = 0;
109         for (int i = 1; i <= n; ++i) G[i].clear();
110         memset(num_block, 0, sizeof num_block);
111         memset(cnt_num, 0, sizeof cnt_num);
112         memset(used, 0, sizeof used); 
113         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
114         for (int i = 1, u, v; i < n; ++i) 
115         {
116             scanf("%d%d", &u, &v);
117             G[u].push_back(v);
118             G[v].push_back(u);  
119         }
120         DFS(1); getpos(1, 1);  
121         while (!sta.empty()) { Belong[sta.top()] = dfssize; sta.pop();}
122         for (int i = 1, u, v; i <= m; ++i)
123         {
124             scanf("%d%d", &u, &v);
125             if (Belong[u] > Belong[v]) swap(u, v);
126             que[i] = qnode(u, v, i, querylca(u, v));
127         }    
128         //divide on tree
129         sort(que + 1, que + 1 + m);  
130         update(que[1].u, que[1].v);
131         work(que[1].lca);
132         ans[que[1].id] = Get();
133         work(que[1].lca);
134         for (int i = 2; i <= m; ++i)
135         {
136             update(que[i - 1].u, que[i].u);
137             update(que[i - 1].v, que[i].v);
138             work(que[i].lca);
139             ans[que[i].id] = Get();
140             work(que[i].lca);
141         } 
142         for (int i = 1; i <= m; ++i) printf("%d\n", ans[i]);
143     }
144     return 0;
145 }
View Code

 

F - 赛题分析

水。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 1010
 5 #define INF 0x3f3f3f3f
 6 int t, n, m;
 7 int arr[N], brr[N];
 8 
 9 int main()
10 {
11     scanf("%d", &t);
12     for (int kase = 1; kase <= t; ++kase)
13     {
14         printf("Problem %d:\n", kase + 1000);
15         scanf("%d%d", &n, &m);
16         for (int i = 1; i <= n; ++i) scanf("%d", arr + i);
17         if (n == 0) puts("Shortest judge solution: N/A bytes.");
18         else printf("Shortest judge solution: %d bytes.\n", *min_element(arr + 1, arr + 1 + n));
19         for (int i = 1; i <= m; ++i) scanf("%d", brr + i);
20         if (m == 0) puts("Shortest team solution: N/A bytes.");
21         else printf("Shortest team solution: %d bytes.\n", *min_element(brr + 1, brr + 1 + m));
22     }
23     return 0;
24 }
View Code

 

G - quailty算法

留坑。

 

H - SA-IS后缀数组

题意:求每对相邻的后缀字符的字典序大小

思路:从后面往前推,只考虑最高位,如果最高位相同,那么问题转化为一个子问题

比如 cm 和 acm  考虑最高位 如果最高位相同 问题转化为 m 和 cm 的大小关系

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 1000010
 5 int t, n;
 6 char s[N];
 7 int ans[N];
 8 
 9 int main()
10 {
11     scanf("%d", &t);
12     while (t--)
13     {
14         int n;
15         scanf("%d%s", &n, s);
16         int len = strlen(s);
17         if (s[len - 1] != s[len - 2]) ans[len - 2] = s[len - 2] > s[len - 1];
18         else ans[len - 2] = 1;
19         for (int i = len - 3; i >= 0; --i)
20         {
21             if (s[i] != s[i + 1]) ans[i] = s[i] > s[i + 1];
22             else ans[i] = ans[i + 1];
23         }
24         for (int i = 0; i < len - 1; ++i) printf("%c", ans[i] ? '>' : '<');
25         puts("");
26     }
27     return 0;
28 }
View Code

 

 

I - 回文树

Upsolved.

因为数据随机,所以答案不会很大,期望为$O(n)级别$ 那么直接考虑暴力枚举,不满足了立即掐掉

可以先排个序,再双指针加速一下

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 #define N 100010
 5 #define pii pair <int, int>
 6 int t, n, res, a[N];
 7 vector <pii> G[N];
 8 
 9 void DFS(int fx, int x, int fy, int y)
10 {
11     if (a[x] != a[y]) return;
12     if (fx && x == y) return;
13     if (x <= y) ++res;
14     for (int i = 0, j = 0, k = 0, len = G[x].size(); i < len; ++i) if (G[x][i].second != fx)
15     {
16         while (j < G[y].size() && G[y][j].first < G[x][i].first) ++j;
17         while (k < G[y].size() && G[y][k].first <= G[x][i].first) ++k;
18         for (int o = j; o < k; ++o) if (G[y][0].second != fy) DFS(x, G[x][i].second, y, G[y][o].second);    
19     }
20 }
21 
22 int main()
23 {
24     scanf("%d", &t);
25     while (t--)
26     {
27         scanf("%d", &n);
28         for (int i = 1; i <= n; ++i) G[i].clear();
29         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
30         for (int i = 1, u, v; i < n; ++i)
31         {
32             scanf("%d%d", &u, &v);
33             G[u].push_back(pii(a[v], v));
34             G[v].push_back(pii(a[u], u));
35         }
36         for (int i = 1; i <= n; ++i) sort(G[i].begin(), G[i].end());
37         res = 0;
38         for (int i = 1; i <= n; ++i) DFS(0, i, 0, i); 
39         for (int i = 1; i <= n; ++i) for (auto it : G[i]) DFS(it.second, i, i, it.second);
40         printf("%d\n", res);
41     }
42     return 0;
43 }
View Code

 

 

J - 代码派对

留坑。

 

K - CCPC直播

按题意模拟即可。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int t; 
 5 char s[20], sta[20];
 6 int Rank, x, pro;
 7 
 8 int main()
 9 {
10     scanf("%d", &t);
11     while (t--)
12     {
13         scanf("%d%s%d%s", &Rank, s, &pro, sta);
14         printf("%3d|%-16s|%d|[", Rank, s, pro);        
15         if (strcmp(sta, "Running") == 0) 
16         {
17             scanf("%d", &x);
18             for (int i = 0; i < x; ++i) putchar('X');
19             for (int i = x; i < 10; ++i) putchar(' ');
20             printf("]\n");
21         }
22         else
23         {
24             if (strcmp(sta, "FB") == 0) strcpy(sta, "AC*");
25             printf("    ");
26             printf("%-6s]\n", sta);
27         }
28     }
29     return 0;
30 }
View Code
posted @ 2018-10-25 17:53  Dup4  阅读(372)  评论(0编辑  收藏  举报