• 2019 HDOJ Multi-University Training Contest Stage 4(杭电多校)


    很抱歉过了这么多天才补这场,最近真的挺忙的……

    出题人是朝鲜的(目测是金策工业?),挺难。

    题目链接:http://acm.hdu.edu.cn/contests/contest_show.php?cid=851


    A:

    签到题。

    对于当前的点,若其编号为偶数,则可与1相连使得边权贡献为0。否则从低位向高位找当前点编号的二进制表示的第一个0,使这个0变为1,其他位置变为0并检查新的数字是否小于等于n。若小于等于n则贡献为0,反之贡献为1。

     1 /* basic header */
     2 #include <bits/stdc++.h>
     3 /* define */
     4 #define ll long long
     5 #define dou double
     6 #define pb emplace_back
     7 #define mp make_pair
     8 #define sot(a,b) sort(a+1,a+1+b)
     9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep0(i,a,b) for(int i=a;i<b;++i)
    11 #define eps 1e-8
    12 #define int_inf 0x3f3f3f3f
    13 #define ll_inf 0x7f7f7f7f7f7f7f7f
    14 #define lson (curpos<<1)
    15 #define rson (curpos<<1|1)
    16 /* namespace */
    17 using namespace std;
    18 /* header end */
    19 
    20 const int maxn = 2e7;
    21 ll bin[60];
    22 int ans[maxn];
    23 
    24 int main() {
    25     bin[0] = 1;
    26     for (int i = 1; i <= 40; i++) bin[i] = (bin[i - 1] << 1);
    27     int T; cin >> T;
    28     while (T--) {
    29         int n;
    30         cin >> n;
    31         int sum = 0;
    32         for (int i = 1; i <= n; i++) {
    33             if (!(i & 1)) {
    34                 ans[i] = 1;
    35                 continue;
    36             }
    37             for (int j = 0; j <= 31; j++) {
    38                 if ((i & bin[j]) == 0) {
    39                     if (bin[j] <= n) ans[i] = bin[j];
    40                     else {
    41                         ans[i] = 1;
    42                         sum++;
    43                     }
    44                     break;
    45                 }
    46             }
    47         }
    48         cout << sum << endl;
    49         for (int i = 2; i <= n - 1; i++) cout << ans[i] << " ";
    50         cout << ans[n] << endl;
    51     }
    52     return 0;
    53 }
    View Code

    C:

    思维题。参考:https://blog.csdn.net/liufengwei1/article/details/97970041

    对于n/k为偶数的情况蛇形填数即可,奇数时只要考虑前3k个,然后剩下就变成了偶数的情况。

     1 /*************************************************************************
     2 *File Name: c.cpp
     3 *Author: JHSeng
     4 *zxc98567@163.com
     5 *Created Time: Sun 11 Aug 2019 12:39:55 AM CST
     6  ************************************************************************/
     7 /* basic header */
     8 #include <bits/stdc++.h>
     9 /* define */
    10 #define ll long long
    11 #define dou double
    12 #define pb emplace_back
    13 #define ans make_pair
    14 #define sot(a,b) sort(a+1,a+1+b)
    15 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    16 #define rep0(i,a,b) for(int i=a;i<b;++i)
    17 #define eps 1e-8
    18 #define int_inf 0x3f3f3f3f
    19 #define ll_inf 0x7f7f7f7f7f7f7f7f
    20 #define lson (curpos<<1)
    21 #define rson (curpos<<1|1)
    22 /* namespace */
    23 using namespace std;
    24 /* header end */
    25 
    26 int main() {
    27     int t; scanf("%d", &t);
    28     while (t--) {
    29         int n, k; scanf("%d%d", &n, &k);
    30         if ((ll)n * (n + 1) / 2 % k || (n == k && n != 1)) {
    31             puts("no");
    32             continue;
    33         }
    34         puts("yes");
    35         int x = k, y = n / k, ans[x + 5][y + 5];
    36         if (y & 1) {
    37             for (int i = 1; i <= x; i++) ans[i][1] = i;
    38             ans[k / 2 + 1][2] = 2 * k;
    39             for (int i = k / 2 + 2; i <= x; i++) ans[i][2] = i - k / 2 - 1 + k;
    40             for (int i = 1; i <= k / 2; i++) ans[i][2] = k + k / 2 + i;
    41             for (int i = 1; i <= x; i++) ans[i][3] = 4 * k + k / 2 + 2 - ans[i][1] - ans[i][2];
    42             int nx = 1, ny = 4;
    43             for (int i = 3 * k + 1; i <= n; i++) {
    44                 ans[nx][ny] = i;
    45                 if (!(ny % 2)) {
    46                     if (nx == x) ny++;
    47                     else nx++;
    48                 } else {
    49                     if (nx == 1) ny++;
    50                     else nx--;
    51                 }
    52             }
    53         } else {
    54             int nx = 1, ny = 1;
    55             for (int i = 1; i <= n; i++) {
    56                 ans[nx][ny] = i;
    57                 if (ny % 2 == 1) {
    58                     if (nx == x) ny++;
    59                     else nx++;
    60                 } else {
    61                     if (nx == 1) ny++;
    62                     else nx--;
    63                 }
    64             }
    65         }
    66         for (int i = 1; i <= x; i++)
    67             for (int j = 1; j <= y; j++)
    68                 printf("%d%c", ans[i][j], j == y ? '
    ' : ' ');
    69     }
    70     return 0;
    71 }
    View Code

    F:

    有一匹马要跳过n棵树,跳过一棵树所消耗的体力等同于树的高度,获得的分数等同于剩余体力。有两种操作:一是在跳一棵树之前把树吃掉,最多m次;二是跳完一棵树之后休息,把体力恢复成已经吃掉的树的高度和,这种操作最多k次。初始体力为0,求最大分数。

    休息k次就是把序列分成k+1段,每段贡献分数是负的前缀和的前缀和。考虑吃树,若吃完树之后若在同一段,相当于后面每个位置不用减去这棵树的权值,若不在同一段相当于每个位置会获得这棵树的权值,即分数为a[i]*(n-i+1),这个东西求前m大即可。

    显然斜率优化dp。

     1 /* basic header */
     2 #include <bits/stdc++.h>
     3 /* define */
     4 #define ll long long
     5 #define dou double
     6 #define pb emplace_back
     7 #define mp make_pair
     8 #define sot(a,b) sort(a+1,a+1+b)
     9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep0(i,a,b) for(int i=a;i<b;++i)
    11 #define eps 1e-8
    12 #define int_inf 0x3f3f3f3f
    13 #define ll_inf 0x7f7f7f7f7f7f7f7f
    14 #define lson (curpos<<1)
    15 #define rson (curpos<<1|1)
    16 /* namespace */
    17 using namespace std;
    18 /* header end */
    19 
    20 const int maxn = 1e4 + 10;
    21 ll dp[55][maxn], sum1[maxn], sum2[maxn], score[maxn];
    22 int a[maxn];
    23 
    24 ll X (int i) {return sum1[i];}
    25 
    26 ll Y(int t, int i) {return dp[t][i] - sum2[i] + i * sum1[i];}
    27 
    28 int main() {
    29     int t; scanf("%d", &t);
    30     while (t--) {
    31         ll ans = 0;
    32         int n, k, m, que[maxn]; scanf("%d%d%d", &n, &k, &m);
    33         for (int i = 1; i <= n; i++) {
    34             scanf("%d", &a[i]);
    35             sum1[i] = sum1[i - 1] + a[i]; sum2[i] = sum2[i - 1] + sum1[i];
    36             score[i] = (ll)a[i] * (n - i + 1);
    37         }
    38         sort(score + 1, score + 1 + n);
    39         for (int i = n - m + 1; i <= n; i++) ans += score[i];
    40         memset(dp, 0x3f, sizeof(dp)); dp[0][0] = 0;
    41         for (int i = 1; i <= k + 1; i++) {
    42             int head = 0, tail = 0;
    43             que[tail++] = 0;
    44             for (int j = 1; j <= n; j++) {
    45                 while (head + 1 < tail && (Y(i - 1, que[head + 1]) - Y(i - 1, que[head]) <= j * (X(que[head + 1]) - X(que[head]))))
    46                     head++;
    47                 dp[i][j] = dp[i - 1][que[head]] + sum2[j] - sum2[que[head]] - (j - que[head]) * sum1[que[head]];
    48                 while (head + 1 < tail && (Y(i - 1, que[tail - 1]) - Y(i - 1, que[tail - 2])) * (X(j) - X(que[tail - 1])) >= (Y(i - 1, j) - Y(i - 1, que[tail - 1])) * (X(que[tail - 1]) - X(que[tail - 2])))
    49                     tail--;
    50                 que[tail++] = j;
    51             }
    52         }
    53         ans -= dp[k + 1][n];
    54         printf("%lld
    ", ans);
    55     }
    56     return 0;
    57 }
    View Code

    G:

    一开始还以为是反向bfs,白给了两发。

    题目说明120步之后就能作判断。可以先比较初始矩阵和目标矩阵数字1、2、3、4的位置,再比较5、6、7、8,以此类推。因为前面的数排完之后就没有后效性了。可以从1*n的矩阵思考,再数学归纳到n*n来思考这个问题。

    事实上这是个关于奇数码游戏(就是题目给的游戏)的结论题:奇数码游戏两个局面可达,当且仅当两个局面下网格中的数依次写成一行含有n^2-1个元素的序列中,逆序对个数的奇偶性相同。该结论必要性显然:当空格左右移动时,写成的序列显然不变,不改变逆序对个数奇偶性;空格上下移动时,相当于某个数与它前(或后)边的n-1个数交换了位置,因为n-1是购书,所以逆序对数的变化也只能是偶数。

     1 /* basic header */
     2 #include <bits/stdc++.h>
     3 /* define */
     4 #define ll long long
     5 #define dou double
     6 #define pb emplace_back
     7 #define mp make_pair
     8 #define sot(a,b) sort(a+1,a+1+b)
     9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep0(i,a,b) for(int i=a;i<b;++i)
    11 #define eps 1e-8
    12 #define int_inf 0x3f3f3f3f
    13 #define ll_inf 0x7f7f7f7f7f7f7f7f
    14 #define lson (curpos<<1)
    15 #define rson (curpos<<1|1)
    16 /* namespace */
    17 using namespace std;
    18 /* header end */
    19 
    20 const int maxn = 20;
    21 
    22 int main() {
    23     int t; scanf("%d", &t);
    24     while (t--) {
    25         int ans = 0, a[maxn];
    26         rep0(i, 0, 16) {
    27             scanf("%d", &a[i]);
    28             if (!a[i]) ans += i / 4 + 1 + i % 4 + 1, a[i] = 16;
    29             rep1(j, 0, i) if (a[j] > a[i]) ans++;
    30         }
    31         if (ans & 1) puts("No");
    32         else puts("Yes");
    33     }
    34     return 0;
    35 }
    View Code

    H:

    给定一维坐标系上的n个整点和m次询问,每次询问给定L,R,p,K。问在区间[L,R]内到点p距离第K小,输出其距离。

    二分答案,看区间[p-ans,p+ans]内有没有k个数。

     1 /* basic header */
     2 #include <bits/stdc++.h>
     3 /* define */
     4 #define ll long long
     5 #define dou double
     6 #define pb emplace_back
     7 #define mp make_pair
     8 #define sot(a,b) sort(a+1,a+1+b)
     9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep0(i,a,b) for(int i=a;i<b;++i)
    11 #define eps 1e-8
    12 #define int_inf 0x3f3f3f3f
    13 #define ll_inf 0x7f7f7f7f7f7f7f7f
    14 #define lson (curpos<<1)
    15 #define rson (curpos<<1|1)
    16 /* namespace */
    17 using namespace std;
    18 /* header end */
    19 
    20 const int maxn = 1e6 + 10;
    21 int a[maxn], root[maxn], cnt = 0;
    22 
    23 struct Node {
    24     int l, r, sum;
    25 } segt[maxn * 40];
    26 
    27 void update(int pos, int curl, int curr, int &curroot, int &lastroot) {
    28     segt[++cnt] = segt[lastroot], segt[cnt].sum++, curroot = cnt;
    29     if (curl == curr) return;
    30     int mid = curl + curr >> 1;
    31     if (pos <= mid) update(pos, curl, mid, segt[curroot].l, segt[lastroot].l);
    32     else update(pos, mid + 1, curr, segt[curroot].r, segt[lastroot].r);
    33 }
    34 
    35 int query(int lRoot, int rRoot, int curl, int curr, int ql, int qr) {
    36     if (ql <= curl && curr <= qr)
    37         return segt[rRoot].sum - segt[lRoot].sum;
    38     if (curl == curr) return 0;
    39     int mid = curl + curr >> 1;
    40     if (qr <= mid) return query(segt[lRoot].l, segt[rRoot].l, curl, mid, ql, qr);
    41     else if (ql > mid) return query(segt[lRoot].r, segt[rRoot].r, mid + 1, curr, ql, qr);
    42     else return query(segt[lRoot].l, segt[rRoot].l, curl, mid, ql, mid) + query(segt[lRoot].r, segt[rRoot].r, mid + 1, curr, mid + 1, qr);
    43 }
    44 
    45 int main() {
    46     int t; scanf("%d", &t);
    47     while (t--) {
    48         cnt = 0;
    49         int n, q, maxx; scanf("%d%d", &n, &q);
    50         for (int i = 1; i <= n; i++) {
    51             scanf("%d", &a[i]);
    52             maxx = max(maxx, a[i]);
    53         }
    54         for (int i = 1; i <= n; i++)
    55             update(a[i], 1, maxx, root[i], root[i - 1]);
    56         int lastAns = 0;
    57         while (q--) {
    58             int l, r, p, k; scanf("%d%d%d%d", &l, &r, &p, &k);
    59             l ^= lastAns, r ^= lastAns, p ^= lastAns, k ^= lastAns;
    60             int upBound = maxx, lowBound = 0, ans = maxx;
    61             while (lowBound <= upBound) {
    62                 int mid = lowBound + upBound >> 1;
    63                 if (query(root[l - 1], root[r], 1, maxx, p - mid, p + mid) >= k) {
    64                     ans = mid;
    65                     upBound = mid - 1;
    66                 } else lowBound = mid + 1;
    67             }
    68             lastAns = ans;
    69             printf("%d
    ", ans);
    70         }
    71     }
    72     return 0;
    73 }
    View Code

    J:

    给定正整数n(n>=2),把n唯一分解之后输出最小的幂次。

    把n用4000以内的质数分解,然后判断剩下的是否为p2,p3,p4,p2q2的形式即可,若都不是,答案为1。

     1 /* basic header */
     2 #include <bits/stdc++.h>
     3 /* define */
     4 #define ll long long
     5 #define dou double
     6 #define pb emplace_back
     7 #define mp make_pair
     8 #define sot(a,b) sort(a+1,a+1+b)
     9 #define rep1(i,a,b) for(int i=a;i<=b;++i)
    10 #define rep0(i,a,b) for(int i=a;i<b;++i)
    11 #define eps 1e-8
    12 #define int_inf 0x3f3f3f3f
    13 #define ll_inf 0x7f7f7f7f7f7f7f7f
    14 #define lson (curpos<<1)
    15 #define rson (curpos<<1|1)
    16 /* namespace */
    17 using namespace std;
    18 /* header end */
    19 
    20 const int maxn = 4010;
    21 int t, tot, p[maxn], vis[maxn];
    22 ll n;
    23 
    24 void getPrime() {
    25     for (int i = 2; i < maxn; i++) {
    26         if (!vis[i]) p[tot++] = i;
    27         for (int j = 0; j < tot && i * p[j] < maxn; j++) {
    28             vis[i * p[j]] = 1;
    29             if (i % p[j] == 0) break;
    30         }
    31     }
    32 }
    33 
    34 int main() {
    35     getPrime();
    36     int t; scanf("%d", &t);
    37     while (t--) {
    38         scanf("%lld", &n);
    39         int cnt = int_inf, flag = 0;
    40         for (int i = 0; i < tot; i++)
    41             if (n % p[i] == 0) {
    42                 int num = 0;
    43                 while (n % p[i] == 0) {
    44                     num++; n /= p[i];
    45                 }
    46                 if (num == 1) flag = 1;
    47                 cnt = min(cnt, num);
    48             }
    49         if (flag) {
    50             puts("1");
    51             continue;
    52         }
    53         if (n == 1) {
    54             printf("%d
    ", cnt);
    55             continue;
    56         }
    57         ll tmp = pow(n, 0.25);
    58         if (tmp * tmp * tmp * tmp == n) cnt = min(cnt, 4);
    59         else {
    60             ++tmp;
    61             if (tmp * tmp * tmp * tmp == n) cnt = min(cnt, 4);
    62             else {
    63                 tmp = pow(n, 0.5);
    64                 if (tmp * tmp == n) cnt = min(cnt, 2);
    65                 else {
    66                     tmp++;
    67                     if (tmp * tmp == n) cnt = min(cnt, 2);
    68                     else {
    69                         tmp = pow(n, 1.0 / 3);
    70                         if (tmp * tmp * tmp == n) cnt = min(3, cnt);
    71                         else {
    72                             tmp++;
    73                             if (tmp * tmp * tmp == n) cnt = min(3, cnt);
    74                             else cnt = min(1, cnt);
    75                         }
    76                     }
    77                 }
    78             }
    79         }
    80         printf("%d
    ", cnt);
    81     }
    82     return 0;
    83 }
    View Code
  • 相关阅读:
    ubuntu(16.04.01)学习-day2
    python学习day5--set、函数
    ubuntu(16.04.01)学习-day1
    nosql
    redis学习-day1
    scrapy框架梳理
    io多路复用--本质
    异步非阻塞--高性能相关
    爬虫设计模式总结
    requests模块参数介绍
  • 原文地址:https://www.cnblogs.com/JHSeng/p/11279703.html
Copyright © 2020-2023  润新知