• ZOJ Monthly, January 2019


    A: Little Sub and Pascal's Triangle

    Solved.

    题意:

    求杨辉三角第n行奇数个数

    思路:

    薛聚聚说找规律,16说Lucas

    答案是 $2^p ;;p 为 n - 1 中 以2进制表示下1的个数$

    证明

    $Ans = sumlimits_0^n C_n^i ;\%; 2 = sumlimits_0^n C_{frac{n}{2}}^{frac{i}{2}} cdot C_{n;\%;2}^{i;\%;2}$

    我们考虑 $C_{n ;\%; 2}^{i ;\%; 2}$ 一共有四种取值

    $C_0^0 ;; C_0^1;; C_1^0 ;; C_1^1$

    我们发现 只有 $C_0^1的值为0 其他三个值都为1$

    那么我们再考虑$C_n^i 这个式子$

    它通过卢卡斯定理分解 实际上可以写成

    我们先假设 

    $i 以二进制表示为$

    $a_1, a_2, cdots a_k$

    $n 以二进制表示为$

    $b_1, b_2, cdots b_k$

    那么 $C_n^i = C_{b_1}^{a_1} cdot C_{b_2}^{a_2} cdots C_{b_k}^{a_k}$

    那么我们发现,

    要满足$C_n^i;\%; 2 = 1 ;;$

    $那么在b_y = 1的位置上,i在对应位置上取0或者1都可以$

    在$b_y = 0 的位置上,i在对应位置的取值已经固定 是 0$

    那么$i的取值一共有2^p  p 为(n - 1)以2进制表示下1的个数$

    为什么是$n - 1 ;;因为杨辉三角是从第0行开始的$

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 ll n;
     8 
     9 int main()
    10 {
    11     int t;
    12     scanf("%d", &t);
    13     while(t--)
    14     {
    15         scanf("%lld", &n);
    16         n--;
    17         ll tmp = 0;
    18         while(n)
    19         {
    20             if(n & 1) tmp++;
    21             n >>= 1;
    22         }
    23         ll ans = 1ll << tmp;
    24         printf("%lld
    ", ans);
    25     }
    26     return 0;
    27 }
    View Code

    B:Little Sub and his Geometry Problem

    Solved.

    题意:

    一个点的权值定义为它到左下角所有点的曼哈顿距离

    q次查询, 每次查询权值为c的点的个数

    思路:

    $给出的点沿着x轴正方向, y轴正方向都是严格单调递增的。$

    $因此可以枚举x轴, 动态维护左下角点个数以及权值, 向右走的同时$

    $将横坐标相同, 纵坐标<=当前位置的点假如, 向下走的时候将纵坐标相同给的点移除$

    $当前权值为c时 ans++$

    (薛聚聚:不会写题解啊)

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 typedef unsigned long long ull;
     7 
     8 const double eps = 1e-8;
     9 const ll MOD = 1e9 + 7;
    10 const ll INFLL = 0x3f3f3f3f3f3f3f3f;
    11 const int INF = 0x3f3f3f3f;
    12 const int maxn = 1e5 + 10;
    13 
    14 int n, k;
    15 ll sum, cnt;
    16 ll sum_arr[maxn], cnt_arr[maxn];
    17 ll ans[20];
    18 
    19 struct node {
    20     int x, y;
    21     node() {}
    22     node(int x, int y) :x(x), y(y) {}
    23     bool operator < (const node &other) const
    24     {
    25         return x == other.x ? y < other.y : x < other.x;
    26     }
    27 }P[maxn];
    28 
    29 ll solve(ll c)
    30 {
    31     cnt = sum = 0;
    32     memset(sum_arr, 0, sizeof sum_arr);
    33     memset(cnt_arr, 0, sizeof cnt_arr);
    34     int index = 1;
    35     int ans = 0;
    36     int y = n;
    37     for (int x = 1; x <= n; ++x)
    38     {
    39         while (index <= k && P[index].x <= x)
    40         {
    41             if (P[index].y <= y)
    42             {
    43                 cnt++;
    44                 sum += P[index].x + P[index].y;
    45                 sum_arr[P[index].y] += P[index].x + P[index].y;
    46                 cnt_arr[P[index].y]++;
    47             }
    48             ++index;
    49         }
    50         while ((x + y) * cnt - sum > c)
    51         {
    52             sum -= sum_arr[y];
    53             cnt -= cnt_arr[y];
    54             --y;
    55         }
    56         if ((x + y) * cnt - sum == c) ++ans;
    57     }
    58     return ans;
    59 }
    60 
    61 void RUN()
    62 {
    63     int t;
    64     scanf("%d", &t);
    65     while (t--)
    66     {
    67         scanf("%d %d", &n, &k);
    68         for (int i = 1; i <= k; ++i) scanf("%d %d", &P[i].x, &P[i].y);
    69         sort(P + 1, P + 1 + k);
    70         int q;
    71         scanf("%d", &q);
    72         for (int i = 1; i <= q; ++i)
    73         {
    74             ll c;
    75             scanf("%lld
    ", &c);
    76             ans[i] = solve(c);
    77         }
    78         for (int i = 1; i <= q; ++i) printf("%lld%c", ans[i], " 
    "[i == q]);
    79     }
    80 }
    81 
    82 int main()
    83 {
    84 #ifdef LOCAL_JUDGE
    85     freopen("Text.txt", "r", stdin);
    86 #endif // LOCAL_JUDGE
    87 
    88     RUN();
    89 
    90 #ifdef LOCAL_JUDGE
    91     fclose(stdin);
    92 #endif // LOCAL_JUDGE
    93     return 0;
    94 }
    View Code

    E:Little Sub and Mr.Potato's Math Problem

    Solved.

    题意:

    给出n, k

    将n个数按照字典序排序, k所在的位置为m

    现在给出k, m  求最小的n

    思路:

    当k为10的整数倍, 那么它一定在第$log_{10^k}$

    $随后统计当n=k的时候, 排在k前面的个数,和m比较, 判断是否合法$

    $接着不断增加n, 统计每次增长排在k前面的个数, 随后输出n$

    (薛聚聚:不会写题解啊)

      1 #include<bits/stdc++.h>
      2 
      3 using namespace std;
      4 
      5 typedef long long ll;
      6 typedef unsigned long long ull;
      7 
      8 const double eps = 1e-8;
      9 const ll MOD = 1e9 + 7;
     10 const ll INFLL = 0x3f3f3f3f3f3f3f3f;
     11 const int INF = 0x3f3f3f3f;
     12 const int maxn = 1e5 + 10;
     13 
     14 ll k, m;
     15 int arr[maxn];
     16 ll pow_10[10];
     17 
     18 void Init()
     19 {
     20     pow_10[0] = 1;
     21     for (int i = 1; i <= 18; ++i)
     22     {
     23         pow_10[i] = pow_10[i - 1] * 10;
     24     }
     25 }
     26 
     27 void solve()
     28 {
     29     ll num = 1;
     30     for (int i = 1;; ++i)
     31     {
     32         if (num > k) break;
     33         else if (num == k)
     34         {
     35             if (i == m)
     36             {
     37                 printf("%lld
    ", k);
     38                 return;
     39             }
     40             else
     41             {
     42                 puts("0");
     43                 return;
     44             }
     45         }
     46         num *= 10;
     47     }
     48     int len = 0;
     49     num = k;
     50     while (num)
     51     {
     52         arr[++len] = num % 10;
     53         num /= 10;
     54     }
     55     reverse(arr + 1, arr + 1 + len);
     56     ll ans = 0;
     57     num = 0;
     58     for (int i = 1; i <= len; ++i)
     59     {
     60         num = num * 10 + arr[i];
     61         ans += num - pow_10[i - 1];
     62         if (i != len) ++ans;
     63     }
     64     if (ans >= m)
     65     {
     66         puts("0");
     67         return;
     68     }
     69     else if (ans == m - 1)
     70     {
     71         printf("%lld
    ", k);
     72         return;
     73     }
     74     while (1)
     75     {
     76         len++;
     77         num *= 10;
     78         if (ans + num - pow_10[len - 1] >= m - 1)
     79         {
     80             ans = pow_10[len - 1] + m - ans - 2;
     81             printf("%lld
    ", ans);
     82             return;
     83         }
     84         ans += num - pow_10[len - 1];
     85     }
     86 }
     87 
     88 void RUN()
     89 {
     90     Init();
     91     int t;
     92     scanf("%d", &t);
     93     while (t--)
     94     {
     95         scanf("%lld %lld", &k, &m);
     96         solve();
     97     }
     98 }
     99 
    100 int main()
    101 {
    102 #ifdef LOCAL_JUDGE
    103     freopen("Text.txt", "r", stdin);
    104 #endif // LOCAL_JUDGE
    105 
    106     RUN();
    107 
    108 #ifdef LOCAL_JUDGE
    109     fclose(stdin);
    110 #endif // LOCAL_JUDGE
    111     return 0;
    112 }
    View Code

    F:Little Sub and a Game

    Unsolved.

    题意:

    有两个玩家$A, B 刚开始有一个变量v = 0$

    $A玩家有N个pair, B玩家有M个pair ;; pair 为(x, y) A玩家N次操作,每次选择x_i 或者 y_i 来异或v B玩家有M次操作$

    $A玩家先进行N次操作, B玩家再进行M次操作$

    A玩家想让$v尽量大,B玩家想让v尽量小$

    两个玩家都采用最优策略,求最后$v$的值

    G:Little Sub and Tree

    Solved.

    题意:

    给出一个无根树,选取$k个点对所有点进行编码$

    按如下方式进行编码

    $令选取的k个点为 s_1, s_2 cdots s_k$

    编出的码有$k位$

    $对于u来说,第i位的编码为 s_i -> u的简单路径上的点的总数$

    思路:

    如果是一条链的话  那么取两端的一个就可以了

    那么我们考虑一棵树中,如果某个节点的儿子对应的子树是一条链

    那么这条链是可以被缩点成一个叶节点 而对答案没有影响

    那么现在树就被我们简化成了 只有叶节点的子树

    首先注意到,一棵子树内节点的区分和这棵子树外的点的选取是没有关系的

    那么我们考虑 一个点对应的儿子当中,如果有$x个叶节点$

    那么这x个节点要想被区分,就需要取$x - 1$ 个

    再考虑一个点的儿子对应的子树,如果子树内都被区分了,那么合并起来也是被区分的

    那么考虑选谁作为根

    只要根不在链上就可以了,因为如果在链上会对缩点产生影响

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 100010
     5 int t, n, root, d[N], fa[N];
     6 vector <int> G1[N], G2[N], res;
     7 
     8 int pre(int u)
     9 {
    10     int id = -1;
    11     int cnt = G1[u].size() - 1;
    12     if (cnt == 0) return u;
    13     for (auto v : G1[u]) if (v != fa[u])    
    14     {
    15         fa[v] = u; 
    16         id = pre(v);
    17         G2[u].push_back(id);
    18     }
    19     if (cnt == 1 && u != root) return id;
    20     else return u;
    21 }
    22 
    23 void DFS(int u)
    24 {
    25     int need = 0;
    26     for (auto v : G2[u]) if (v != fa[u] && !d[v])
    27         ++need;
    28     --need;
    29     for (auto v : G2[u]) if (v != fa[u])
    30     {
    31         fa[v] = u;
    32         if (!d[v] && need > 0)
    33         {
    34             --need;
    35             res.push_back(v);
    36         }
    37         DFS(v);
    38     }
    39 }
    40 
    41 int main()
    42 {
    43     scanf("%d", &t);
    44     while (t--)
    45     {
    46         scanf("%d", &n);
    47         for (int i = 1; i <= n; ++i) 
    48         {
    49             G1[i].clear();
    50             G2[i].clear();
    51             d[i] = -1;
    52             fa[i] = 0;
    53         }
    54         res.clear();
    55         root = -1;
    56 
    57         for (int i = 1, u, v; i < n; ++i)
    58         {
    59             scanf("%d%d", &u, &v);
    60             G1[u].push_back(v);
    61             G1[v].push_back(u);
    62             ++d[u]; ++d[v];
    63         }
    64         if (n == 2)
    65         {
    66             puts("1
    1");
    67             continue;
    68         }
    69         for (int i = 1; i <= n; ++i) if (d[i] > 1)
    70         {
    71             root = i;
    72             break;
    73         }
    74         if(root == -1)
    75         {
    76             int ans = 0;
    77             for(int i = 1; i <= n; ++i) if(d[i] == 0) ans = i;
    78             printf("1
    %d
    ", ans);
    79             continue;
    80         }
    81         pre(root);
    82         DFS(root);
    83         //puts("bug");
    84         //for (int i = 1; i <= n; ++i) printf("%d %d
    ", i, fa[i]);
    85         //puts("bug");
    86         int k = res.size();
    87         printf("%d
    ", k);
    88         for (int i = 0; i < k; ++i) printf("%d%c", res[i], " 
    "[i == k - 1]);
    89     }
    90     return 0;
    91 }
    View Code

    I:Little Sub and Isomorphism Sequences

    Solved.

    题意:

    有一个$A[], 两种操作$

    • $A_x -> y$
    • 查询最长同构子串

    思路:

    考虑最长同构子串肯定会有重叠部分,那么两端出去的部分就是不同的部分

    那么这个不同的部分让它长度为1即可,因为多余的长度是没有用的

    那么题意就可以转化为 找一个最长的子串,使得两端相同即可

    将数据离散化 开2e5个set维护每个数的位置

    然后用数据结构 维护答案的最大值 即可

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N 200010
     5 int t, n, m, a[N], b[N];
     6 struct qnode
     7 {
     8     int op, x, y;
     9     void scan()
    10     {
    11         scanf("%d", &op);
    12         if (op == 1) 
    13         {
    14             scanf("%d%d", &x, &y);
    15             b[++b[0]] = y;
    16         }
    17     }
    18 }q[N];
    19 set <int> s[N];
    20 namespace SEG
    21 {
    22     int a[N << 2];
    23     void build(int id, int l, int r)
    24     {
    25         a[id] = -1;
    26         if (l == r) return;
    27         int mid = (l + r) >> 1;
    28         build(id << 1, l, mid);
    29         build(id << 1 | 1, mid + 1, r);
    30     }
    31     void update(int id, int l, int r, int pos, int v)
    32     {
    33         if (l == r)
    34         {
    35             a[id] = v;
    36             return;
    37         }
    38         int mid = (l + r) >> 1;
    39         if (pos <= mid) update(id << 1, l, mid, pos, v);
    40         else update(id << 1 | 1, mid + 1, r, pos, v);
    41         a[id] = max(a[id << 1], a[id << 1 | 1]);
    42     }
    43 }
    44 void Hash()
    45 {
    46     sort(b + 1, b + 1 + b[0]);
    47     b[0] = unique(b + 1, b + 1 + b[0]) - b - 1;
    48     for (int i = 1; i <= n; ++i) a[i] = lower_bound(b + 1, b + 1 + b[0], a[i]) - b;
    49     for (int i = 1; i <= m; ++i) if (q[i].op == 1) q[i].y = lower_bound(b + 1, b + 1 + b[0], q[i].y) - b;
    50 }
    51 
    52 int main()
    53 {
    54     scanf("%d", &t);
    55     while (t--)
    56     {
    57         scanf("%d%d", &n, &m);
    58         SEG::build(1, 1, n + m);
    59         for (int i = 1; i <= n + m; ++i) s[i].clear(); b[0] = 0;
    60         for (int i = 1; i <= n; ++i) scanf("%d", a + i), b[++b[0]] = a[i];
    61         for (int i = 1; i <= m; ++i) q[i].scan(); Hash();
    62         for (int i = 1; i <= n; ++i) s[a[i]].insert(i);
    63         for (int i = 1; i <= n + m; ++i) if (s[i].size() >= 2)
    64             SEG::update(1, 1, n + m, i, *s[i].rbegin() - *s[i].begin());
    65         for (int i = 1; i <= m; ++i)
    66         {
    67             if (q[i].op == 1)
    68             {
    69                 int v = a[q[i].x], x = q[i].x, y = q[i].y; 
    70                 s[v].erase(x);
    71                 SEG::update(1, 1, n + m, v, s[v].size() >= 2 ? *s[v].rbegin() - *s[v].begin() : -1);
    72                 a[q[i].x] = y;
    73                 v = y;
    74                 s[v].insert(x);
    75                 SEG::update(1, 1, n + m, v, s[v].size() >= 2 ? *s[v].rbegin() - *s[v].begin() : -1);
    76             }
    77             else printf("%d
    ", SEG::a[1]);
    78         }
    79     }
    80     return 0;
    81 }
    View Code
  • 相关阅读:
    bzoj2045: 双亲数&bzoj1101: [POI2007]Zap
    spoj GCDEX
    jQuery Ajax
    jQuery 动画效果
    jQuery 事件处理API
    jQuery 常用getter&setter
    jQuery 文档操作
    jQuery 基础
    Vue2.2.0+新特性整理
    JavaScript中的HTTP
  • 原文地址:https://www.cnblogs.com/Dup4/p/10292338.html
Copyright © 2020-2023  润新知