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
  • 相关阅读:
    马的遍历 new
    锤子剪刀布 new
    npm 打包 new
    Linux 锁机制
    ubuntu virtualbox 下安装xp,识别usb
    ubuntu设置快捷键
    linux神奇的系统请求系统救命草
    linux 内核动态内存分配测试(纯属娱乐哈)
    C之绝妙(一道很NB的面试题)
    虚拟机virtualbox:Could not find an open hard disk with UUID {368441269e88468698582d1a0568f53c}.
  • 原文地址:https://www.cnblogs.com/Dup4/p/9851609.html
Copyright © 2011-2022 走看看