zoukankan      html  css  js  c++  java
  • Codeforces Round #520 (Div. 2) Solution

    A. A Prank

    Solved.

    题意:

    给出一串数字,每个数字的范围是$[1, 1000]$,并且这个序列是递增的,求最多擦除掉多少个数字,使得别人一看就知道缺的数字是什么。

    思路:

    显然,如果缺的这块数字的个数刚好等于右界 - 左界 + 1 那么就可以知道

    还需要考虑数据范围,因为是$<= 1000  和 >= 1$ 那么对于两边的边界需要特殊考虑。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 110
     5 int n, a[N];
     6 
     7 int main()
     8 {
     9     while (scanf("%d", &n) != EOF)
    10     {
    11         for (int i = 1; i <= n; ++i) scanf("%d", a + i);
    12         a[0] = 0; a[n + 1] = 1001;
    13         int res = 0, tmp = 1;
    14         for (int i = 1; i <= n + 1; ++i)
    15         {
    16             if (a[i] == a[i - 1] + 1) ++tmp;
    17             else
    18             {
    19                 res = max(res, tmp - 2);
    20                 tmp = 1;
    21             }
    22         }
    23         res = max(res, tmp - 2);
    24         printf("%d
    ", res);
    25     }
    26     return 0;
    27 }
    View Code

    B. Math

    Solved.

    题意:

    给出一个数$n$, 有两种操作。

    第一种是乘上一个任意整数$x$

    第二种是开方,并且要保证开方后是整数。

    求最少经过多少次操作,可以得到一个最小的数$n$

    思路:

    考虑$n$的质因数分解形式$a_1^{p_1} cdot a_2^{p_2} cdot a_3^{p_3} ...$

    那么最小的答案就是$a_1 cdot a_2 cdot a_3$

    因为一个数开方后是整数的话,显然是每个质因子的幂次都是偶数次,开方相当于每个质因子的幂次 $ / 2$

    那么显然每个质因子最小的幂次都是1

    再考虑最小的次数,因为乘法可以任意乘一个整数,所以如果需要乘法,那么乘法只需要一次。

    再考虑开方,如果质因子中的最高幂次不是2的幂次,那么它不断$ / 2$ 肯定需要至少一次乘法操作,使得可以继续开方下去,直到幂次变为1

    那么显然要把幂次变成一个第一个大于等于它的2的幂次数,就可以不断$ / 2$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 2000010
     5 int n, Max, res;
     6 int Bit[N], pos[N];
     7 vector <int> v;
     8 
     9 int solve(int x)
    10 {
    11     if (x == 1) return 0;
    12     if (pos[x] == 0) return 1 + lower_bound(Bit + 1, Bit + 1 + 20, x) - Bit; 
    13     for (auto it : v) if (it != x) return 1 + pos[x];
    14     return pos[x];
    15 }
    16 
    17 int main()
    18 {
    19     Bit[0] = 1; pos[1] = 0;  
    20     for (int i = 1; i <= 20; ++i)
    21     {
    22         Bit[i] = Bit[i - 1] << 1;
    23         pos[Bit[i]] = i;
    24     }    
    25     while (scanf("%d", &n) != EOF)
    26     {
    27         if (n == 1) 
    28         {
    29             puts("1 0");
    30             continue;
    31         }
    32         v.clear();
    33         res = 1; Max = 0;
    34         for (int i = 2; i <= n; ++i) 
    35         {
    36             int tmp = 0; 
    37             while (n % i == 0)
    38             { 
    39                 ++tmp; 
    40                 n /= i;
    41             }
    42             if (tmp) 
    43             {
    44                 res *= i;
    45                 Max = max(Max, tmp);
    46                 v.push_back(tmp); 
    47             }
    48         }    
    49         printf("%d %d
    ", res, solve(Max));
    50     }
    51     return 0;
    52 }
    View Code

    C. Banh-mi

    Solved.

    题意:

    给出一个01串,每次询问区间$[l, r]$ 每次可以将区间内一个数取出,并且答案加上这个数的值,区间内剩余的数也加上这个值,求如何安排取出顺序使得答案最大。

    思路:

    显然1要在0之前取,

    我们考虑区间内有$x个1, y 个 0$

    那么考虑取出$x个1的答案$

    显然 取出的数是形如 1 2 4 8 .....

    是一个等比数列,根据求和公式发现答案为$2^x - 1$

    再考虑取出的第一个0的数值为 $2^x - 1$

    也是一个等比数列,和为 $(2^x - 1) cdot (2^y - 1)$

    合并两项答案   即$2^x cdot (2^y - 1)$

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 100010
     6 const ll MOD = (ll)1e9 + 7;
     7 int n, q, a[N];
     8 
     9 ll qmod(ll base, ll n)
    10 {
    11     ll res = 1;
    12     while (n)
    13     {
    14         if (n & 1) res = res * base % MOD;
    15         base = base * base % MOD;
    16         n >>= 1;
    17     }
    18     return res;
    19 }
    20 
    21 int main()
    22 {
    23     while (scanf("%d%d", &n, &q) != EOF)
    24     {
    25         a[0] = 0;
    26         for (int i = 1; i <= n; ++i) scanf("%1d", a + i), a[i] += a[i - 1];
    27         for (int i = 1, l, r; i <= q; ++i) 
    28         {
    29             scanf("%d%d", &l, &r);
    30             int x = a[r] - a[l - 1], y = (r - l + 1) - x;
    31             if (x == 0) 
    32             {
    33                 puts("0");
    34                 continue;
    35             }
    36             printf("%lld
    ", qmod(2, y) * (qmod(2, x) - 1 + MOD) % MOD);
    37         }
    38     }
    39     return 0;
    40 }
    View Code

    D. Fun with Integers

    Solved.

    题意:给出一个数$n$,任意$|a| , |b| < n$ 并且满足 $|a| |b| 互为倍数关系$ 那么答案加上这个倍数,并且这一对$|a|, |b|$不再提供贡献,并且倍数关系$|x| > 1$

    思路:

    考虑一个数$x$, 那么在$[1, n]$ 中是它的倍数的数一共有 $y = lfloor frac {n}{x} floor cdot 2$ 个 因为还有负的

    那么这个数的贡献是$sum_2 ^y  cdot 2$ 再考虑 $-x$ 也会提供一样的贡献 即答案要乘2

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 int n;
     6 
     7 int main()
     8 {
     9     while (scanf("%d", &n) != EOF)
    10     {
    11         ll res = 0;
    12         for (int i = 2; i <= n; ++i)
    13         {
    14             ll x = n / i;
    15             res += 2ll * (x + 2) * (x - 1);
    16         }
    17         printf("%lld
    ", res);
    18     }
    19     return 0;
    20 }
    View Code

    E. Company

    Upsolved.

    题意:

    在一棵树中,每次选择一个区间$[l, r]$ 最多删除一个点,使得这个区间内所有点的$lca$ 的深度最大。

    思路:

    首先有一个点,就是一颗树中一堆点的$LCA$ 其实就是这堆点$DFS序最小 和 最大的两个点的LCA$

    不难证明:

    $我们约定用st[u] 表示点u的DFS序编号,并且约定 st[x] < st[y] <st[z], $

    $根据ST求LCA 显然两个点的LCA是 st[x] 和 st[y] 中间DFS序最小的点,那么再考虑 一个点z $

    $ 此处我们再对z求lca ,普通做法显然是 用st[lca(x, y)]  - st[z] 之间找一个最小的$

    $但实际上没有必要从st[(lca(x, y))] 开始,直接从 st[x] - st[y] 这段中找到的 pos = lca(x, y) 的位置作为左界即可$

    $因为考虑 从st[lca(x, y)] - pos 这一段中,不会有DFS序编号比lca(x, y) 还要小的点,因为显然这一段序列都是在lca(x, y) 的子树中$

    $如此看来,我们约定用u 表示 [l, r] 中DFS序编号最小的点,v 表示编号最大的点$

    $那么LCA 就是 从 st[u] - st[v] 中找一个最小点 即为LCA$

    $再考虑移除哪一个点,我们知道答案跟一段序列的最小值有关,我们要让答案有变化,要让这一段序列的区间长度有变化$

    $显然是移除左边的一个点或者右边的一个点 即 DFS序编号最大的点 或者 DFS序编号最小的点$

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define INF 0x3f3f3f3f
      5 #define N 100010
      6 int n, q, l, r;
      7 vector <int> G[N];
      8 
      9 int p[N], fp[N], sze[N], son[N], fa[N], deep[N], top[N], cnt;
     10 void DFS(int u)
     11 {
     12     sze[u] = 1;
     13     for (auto v : G[u]) if (v != fa[u])
     14     {
     15         fa[v] = u;
     16         deep[v] = deep[u] + 1;
     17         DFS(v); sze[u] += sze[v];
     18         if (!son[u] || sze[v] > sze[son[u]]) son[u] = v;
     19     }
     20 }
     21 
     22 void getpos(int u, int sp = 1)
     23 {
     24     top[u] = sp;
     25     p[u] = ++cnt;
     26     fp[cnt] = u;
     27     if (!son[u]) return;
     28     getpos(son[u], sp);
     29     for (auto v : G[u]) if (v != son[u] && v != fa[u])
     30         getpos(v, v);
     31 }
     32 
     33 int querylca(int u, int v)
     34 {
     35     while (top[u] != top[v])
     36     {
     37         if (deep[top[u]] < deep[top[v]]) swap(u, v);
     38         u = fa[top[u]];
     39     }
     40     if (deep[u] > deep[v]) swap(u, v);
     41     return u;
     42 }
     43 
     44 struct SEG
     45 {
     46     struct node
     47     {
     48         int Max, Min;
     49         void init() { Max = 0, Min = INF; }
     50         node operator + (const node &r) const
     51         {
     52             node res; res.init();
     53             res.Max = max(Max, r.Max);
     54             res.Min = min(Min, r.Min);
     55             return res;    
     56         }
     57     }a[N << 2], res; 
     58     void build(int id, int l, int r)
     59     {
     60         a[id].init();
     61         if (l == r)
     62         {
     63             a[id].Max = a[id].Min = p[l];
     64             return;
     65         }
     66         int mid = (l + r) >> 1;
     67         build(id << 1, l, mid);
     68         build(id << 1 | 1, mid + 1, r);
     69         a[id] = a[id << 1] + a[id << 1 | 1];
     70     }
     71     void query(int id, int l, int r, int ql, int qr)
     72     {
     73         if (l >= ql && r <= qr) 
     74         {
     75             res = res + a[id];
     76             return;
     77         }
     78         int mid = (l + r) >> 1;
     79         if (ql <= mid) query(id << 1, l, mid, ql, qr);
     80         if (qr > mid) query(id << 1 | 1, mid + 1, r, ql, qr);
     81     }
     82 }seg;
     83 
     84 int lca(int l, int r)
     85 {
     86     seg.res.init();
     87     seg.query(1, 1, n, l, r);
     88     return querylca(fp[seg.res.Min], fp[seg.res.Max]);
     89 }
     90 
     91 int work(int x)
     92 {
     93     if (x == l) return deep[lca(l + 1, r)];
     94     if (x == r) return deep[lca(l, r - 1)];
     95     return deep[querylca(lca(l, x - 1), lca(x + 1, r))]; 
     96 }
     97 
     98 void init()
     99 {
    100     for (int i = 1; i <= n; ++i) G[i].clear();
    101     memset(son, 0, sizeof son);
    102     cnt = 0; fa[1] = 0; deep[1] = 0;
    103 }
    104 
    105 int main()
    106 {
    107     while (scanf("%d%d", &n, &q) != EOF)
    108     {
    109         init();
    110         for (int u = 2, v; u <= n; ++u)
    111         {
    112             scanf("%d", &v);
    113             G[u].push_back(v);
    114             G[v].push_back(u);
    115         }
    116         DFS(1); getpos(1); seg.build(1, 1, n);
    117         //for (int i = 1; i <= n; ++i) printf("%d %d %d
    ", i, p[i], fp[i]);
    118         for (int qq = 1; qq <= q; ++qq)
    119         {
    120             scanf("%d%d", &l, &r);
    121             seg.res.init(); seg.query(1, 1, n, l, r);
    122             int x = fp[seg.res.Max], y = fp[seg.res.Min];
    123             int deepx = work(x), deepy = work(y);
    124             if (deepx > deepy) printf("%d %d
    ", x, deepx);
    125             else printf("%d %d
    ", y, deepy); 
    126         }
    127     }
    128     return 0;
    129 }
    View Code

    F. Upgrading Cities

    Unsolved.

  • 相关阅读:
    Neko's loop HDU-6444(网络赛1007)
    Parameters
    SETLOCAL
    RD / RMDIR Command
    devenv 命令用法
    Cannot determine the location of the VS Common Tools folder.
    'DEVENV' is not recognized as an internal or external command,
    How to change Visual Studio default environment setting
    error signing assembly unknown error
    What is the Xcopy Command?:
  • 原文地址:https://www.cnblogs.com/Dup4/p/9961478.html
Copyright © 2011-2022 走看看