zoukankan      html  css  js  c++  java
  • "字节跳动杯"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
    ", 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
    ", (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
    ", 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:
    ", 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.
    ", *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.
    ", *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
    ", 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("]
    ");
    21         }
    22         else
    23         {
    24             if (strcmp(sta, "FB") == 0) strcpy(sta, "AC*");
    25             printf("    ");
    26             printf("%-6s]
    ", sta);
    27         }
    28     }
    29     return 0;
    30 }
    View Code
  • 相关阅读:
    hihoCoder #1062 : 最近公共祖先·一
    hihoCoder #1050 : 树中的最长路
    hihoCoder #1049 : 后序遍历
    108 Convert Sorted Array to Binary Search Tree 将有序数组转换为二叉搜索树
    107 Binary Tree Level Order Traversal II 二叉树的层次遍历 II
    106 Construct Binary Tree from Inorder and Postorder Traversal 从中序与后序遍历序列构造二叉树
    105 Construct Binary Tree from Preorder and Inorder Traversal 从前序与中序遍历序列构造二叉树
    104 Maximum Depth of Binary Tree 二叉树的最大深度
    102 Binary Tree Level Order Traversal 二叉树的层次遍历
    101 Symmetric Tree 判断一颗二叉树是否是镜像二叉树
  • 原文地址:https://www.cnblogs.com/Dup4/p/9851609.html
Copyright © 2011-2022 走看看