• ACM-ICPC 2018 南京赛区网络预赛 Solution


    A. An Olympian Math Problem

    cout << n - 1 << endl;

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 
     6 int t; 
     7 ll n;
     8 
     9 inline void Run() 
    10 {
    11     scanf("%d", &t);
    12     while (t--)
    13     {
    14         scanf("%lld", &n);
    15         printf("%lld
    ", n - 1);
    16     }
    17 }
    18 
    19 int main()
    20 {
    21     #ifdef LOCAL
    22         freopen("Test.in", "r", stdin);
    23     #endif
    24 
    25     Run(); 
    26 
    27     return 0; 
    28 }
    View Code

    B. The writing on the wall

    题意:给出n * m的矩形,找出有多少个子矩形不包含黑块

    思路:枚举每一个当右下角的情况,那么情况总数就是黑块构成的边界里面的格子数量,优先队列优化

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define ll long long
     5 #define N 100010
     6 #define M 110
     7 
     8 int t, n, m, k; 
     9 int G[N][M];
    10 int low[M]; 
    11 
    12 struct node
    13 {
    14     ll h, num;
    15     inline node() {}
    16     inline node(ll h, ll num) : h(h), num(num) {}
    17     inline bool operator < (const node &r) const
    18     {
    19         return h < r.h;  
    20     }
    21 };
    22 
    23 priority_queue <node> q;
    24 
    25 int main()
    26 {
    27 #ifdef LOCAL_JUDGE
    28     freopen("Text.txt", "r", stdin);
    29 #endif // LOCAL_JUDGE
    30     scanf("%d", &t);
    31     for (int kase = 1; kase <= t; ++kase)
    32     {
    33         printf("Case #%d: ", kase); 
    34         memset(G, 0, sizeof G);
    35         memset(low, 0, sizeof low); 
    36         while (!q.empty()) q.pop();
    37         scanf("%d%d%d", &n, &m, &k);
    38         for (int i = 1, x, y; i <= k; ++i)
    39         {
    40             scanf("%d%d", &x, &y);
    41             G[x][y] = 1;
    42         }
    43         ll ans = 0, sum = 0;
    44         for (int i = 1; i <= n; ++i)
    45         {
    46             for (int j = 1; j <= m; ++j)
    47             {
    48                 //if (i % 1000 == 0) cout << i << endl;
    49                 if (G[i][j] == 1)
    50                 {
    51                     while (!q.empty()) q.pop();
    52                     sum = 0;
    53                     low[j] = i;
    54                     continue;
    55                 }
    56                 if (j == 1)
    57                 {
    58                     while (!q.empty()) q.pop();
    59                     sum = 0;
    60                 }                
    61                 ll H = i - low[j];
    62                 ll num = 1;
    63                 while (!q.empty() && q.top().h > H)
    64                 {
    65                     num += q.top().num;
    66                     sum -= q.top().h * q.top().num;
    67                     q.pop();
    68                 }
    69                 sum += num * H;
    70                 ans += sum;
    71                 q.emplace(H, num);
    72             }
    73         }
    74         printf("%lld
    ", ans);
    75     }
    76     return 0;
    77 }
    View Code

     C. GDY

    按题意模拟即可,注意细节

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 int Move[] = { 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 1, 2, };
      5 
      6 struct DT
      7 {
      8     int num[15], cnt;
      9     int score;
     10     inline DT()
     11     {
     12         score = 0; cnt = 0;
     13         memset(num, 0, sizeof num);
     14     }
     15     inline void Get()
     16     {
     17         for (int i = 1; i <= 13; ++i)
     18             score += num[i] * i; 
     19     }
     20 }arr[250];
     21 
     22 int t, n, m;
     23 queue <int> q;
     24 
     25 inline void work()
     26 {
     27     int turn = 1, pre = -1, tot = 0, nx; 
     28     for (int i = 0; i < 13; ++i) if (arr[1].num[Move[i]])
     29     {
     30         pre = Move[i];
     31         --arr[1].num[Move[i]]; 
     32         --arr[1].cnt; 
     33         break;
     34     }
     35     while (true)
     36     {
     37         turn = turn % n + 1;
     38         if (tot == n - 1)
     39         {
     40             for (int i = turn; i <= n; ++i) if (!q.empty()) 
     41             {
     42                 ++arr[i].cnt;
     43                 ++arr[i].num[q.front()]; q.pop();
     44             }
     45             for (int i = 1; i < turn; ++i) if (!q.empty())
     46             {
     47                 ++arr[i].cnt;
     48                 ++arr[i].num[q.front()]; q.pop();
     49             }
     50             for (int i = 0; i < 13; ++i) if (arr[turn].num[Move[i]])
     51             {
     52                 --arr[turn].num[Move[i]];
     53                 if (--arr[turn].cnt == 0) return;
     54                 pre = Move[i]; tot = 0; 
     55                 break;
     56             }
     57         }
     58         else if (pre == 2) tot++;  
     59         else
     60         {
     61             if (pre == 13) nx = 1;
     62             else nx = pre + 1; 
     63             if (arr[turn].num[nx]) 
     64             {
     65                 --arr[turn].num[nx];
     66                 if (--arr[turn].cnt == 0) return;
     67                 pre = nx; tot = 0;
     68             }
     69             else
     70             {
     71                 if (arr[turn].num[2]) 
     72                 {
     73                     --arr[turn].num[2];
     74                     if (--arr[turn].cnt == 0) return;
     75                     pre = 2; tot = 0;
     76                 }
     77                 else tot++; 
     78             }
     79         }
     80     }
     81 }
     82 
     83 inline void Run() 
     84 { 
     85     scanf("%d", &t); 
     86     for (int kase = 1; kase <= t; ++kase)
     87     {
     88         while (!q.empty()) q.pop();
     89         printf("Case #%d:
    ", kase); 
     90         scanf("%d%d", &n, &m);
     91         for (int i = 1, u; i <= m; ++i)
     92         {
     93             scanf("%d", &u);
     94             q.emplace(u);
     95         }
     96         for (int i = 1; i <= n; ++i)
     97         {
     98             arr[i] = DT(); 
     99             for (int j = 1; j <= 5; ++j)
    100             {
    101                 if (!q.empty())
    102                 {
    103                     arr[i].num[q.front()]++; q.pop();
    104                     ++arr[i].cnt;
    105                 }
    106             }
    107         }
    108         work();
    109         for (int i = 1; i <= n; ++i)
    110         {
    111             arr[i].Get();
    112             if (arr[i].score == 0) puts("Winner");
    113             else printf("%d
    ", arr[i].score);
    114         }
    115     }
    116 }
    117 
    118 int main()
    119 {
    120     #ifdef LOCAL 
    121         freopen("Test.in", "r", stdin);
    122     #endif 
    123     
    124     Run();   
    125     return 0;
    126 }
    View Code

     D. Jerome's House

    留坑。

     E. AC Challenge

    题意:有n道题目,每次提交得到分数$t * a_i + b_i$ 有一些题目的提交必须要某些题目提交之后才能提交,求最后获得的最大分数

    思路:记忆化搜索,二进制标记状态 或者 状压DP

     1 #include<bits/stdc++.h>
     2 
     3 using namespace std;
     4 
     5 typedef long long ll;
     6 
     7 ll dp[1 << 20];
     8 
     9 int n;
    10 
    11 struct node {
    12     ll ai, bi;
    13     int state;
    14     inline node(){}
    15     inline node(ll ai, ll bi, int state):ai(ai),bi(bi), state(state){}
    16 }arr[30];
    17 
    18 inline ll DFS(int t, int S)
    19 {
    20     if (t > n) return 0;
    21     if (dp[S] != -1) return dp[S];
    22     ll res = 0;
    23     for (int i = 0; i < n; ++i)
    24     {
    25         int tmp = 1 << i;
    26         if ((tmp & S) == 0)
    27         {
    28             if ((S & arr[i].state) != arr[i].state) continue;
    29             res = max(res, t * arr[i].ai + arr[i].bi + DFS(t + 1, (S | tmp)));
    30         }
    31     }
    32     dp[S] = res;
    33     return res;
    34 }
    35 
    36 inline void RUN()
    37 {
    38     while (~scanf("%d", &n))
    39     {
    40         memset(dp, -1, sizeof dp);
    41         for (int i = 0; i < n; ++i)
    42         {
    43             int m;
    44             int S = 0;
    45             scanf("%lld %lld %d", &arr[i].ai, &arr[i].bi, &m);
    46             while (m--)
    47             {
    48                 int tmp = 0;
    49                 scanf("%d", &tmp);
    50                 S += (1 << (tmp - 1));
    51             }
    52             arr[i].state = S;
    53         }
    54         ll ans = DFS(1, 0);
    55         printf("%lld
    ", ans);
    56     }
    57 }
    58 
    59 int main()
    60 {
    61 #ifdef LOCAL_JUDGE
    62     freopen("Text.txt", "r", stdin);
    63 #endif // LOCAL_JUDGE
    64 
    65     RUN();
    66 
    67 #ifdef LOCAL_JUDGE
    68     fclose(stdin);
    69 #endif // LOCAL_JUDGE
    70 
    71     return 0;
    72 }
    View Code
     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 #define N (1 << 21)
     5 #define ll long long
     6 
     7 struct node
     8 {
     9     ll a, b;
    10     int sta;
    11     inline void scan()
    12     {
    13         int tot, k; sta = 0;
    14         scanf("%lld%lld%d", &a, &b, &tot);
    15         while (tot--)
    16         {
    17             scanf("%d", &k);
    18             sta |= (1 << (k - 1)); 
    19         }
    20     }
    21 }arr[25];
    22 
    23 int n;
    24 ll dp[N];
    25 
    26 inline ll Count(int x)
    27 {
    28     int res = 0;
    29     while (x)
    30     {
    31         ++res;
    32         x &= (x - 1);
    33     }
    34     return res;
    35 }
    36 
    37 inline void Run()
    38 {
    39     while (scanf("%d", &n) != EOF)
    40     {
    41         for (int i = 1; i <= n; ++i) arr[i].scan();
    42         memset(dp, -1, sizeof dp); 
    43         ll ans = 0; dp[0] = 0;
    44         for (int i = 0; i < (1 << n); ++i) 
    45         {
    46             if (dp[i] == -1) continue; 
    47             for (int j = 1; j <= n; ++j)
    48             {
    49                 if (!(i & (1 << (j - 1))) && (i & (arr[j].sta)) == arr[j].sta) 
    50                 {
    51                     int tmp = i | (1 << (j - 1));
    52                     ll t = Count(tmp);
    53                     dp[tmp] = max(dp[tmp], dp[i] + arr[j].a * t + arr[j].b);
    54                     ans = max(ans, dp[tmp]);
    55                 }
    56             }
    57         }
    58         printf("%lld
    ", ans);
    59     }
    60 }
    61 
    62 int main()
    63 {
    64     #ifdef LOCAL 
    65         freopen("Test.in", "r", stdin);
    66     #endif 
    67     
    68     Run();   
    69     return 0;
    70 }
    View Code

     F. An Easy Problem On The Trees

    留坑。

     G. Lpl and Energy-saving Lamps

    题意:有n个房间,每次按顺序换灯泡,一个房间要不所有灯泡都换,要不一个都不换,每个月有固定的新灯泡数,没还完留到下个月,询问第几个月能够换掉几个房间以及剩下的房间数

    思路:线段树维护一个最小值,预处理答案

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define N 100010
      5 #define INF 0x3f3f3f3f
      6 #define ll long long
      7 
      8 typedef pair <int, int> pii;
      9 
     10 int n, m, q, sum;
     11 int arr[N];
     12 pii ans[N]; 
     13 
     14 struct node
     15 {
     16     int l, r, cnt;
     17     int Min, sum;
     18     inline node() {}
     19     inline node(int _l, int _r)
     20     {
     21         l = _l, r = _r;
     22         Min = sum = 0;
     23     }
     24 }tree[N << 2];
     25 
     26 inline void pushup(int id)
     27 {
     28     tree[id].Min = min(tree[id << 1].Min, tree[id << 1 | 1].Min); 
     29     tree[id].sum = tree[id << 1].sum + tree[id << 1 | 1].sum;
     30     tree[id].cnt = tree[id << 1].cnt + tree[id << 1 | 1].cnt;
     31 }
     32 
     33 inline void build(int id, int l, int r)
     34 {
     35     tree[id] = node(l, r);
     36     if (l == r)
     37     {
     38         tree[id].Min = tree[id].sum = arr[l];
     39         tree[id].cnt = 1;
     40         return; 
     41     }
     42     int mid = (l + r) >> 1;
     43     build(id << 1, l, mid);
     44     build(id << 1 | 1, mid + 1, r);
     45     pushup(id);  
     46 }
     47 
     48 int anssum, remind; 
     49 
     50 inline void query(int id)
     51 {
     52     if (tree[id].Min <= remind && tree[id].sum <= remind) 
     53     {
     54         anssum += tree[id].cnt;
     55         sum -= tree[id].sum;
     56         remind -= tree[id].sum;  
     57         tree[id].Min = INF;  
     58         tree[id].sum = 0;
     59         tree[id].cnt = 0;
     60         return; 
     61     }
     62     if (tree[id << 1].Min <= remind) query(id << 1);  
     63     if (tree[id << 1 | 1].Min <= remind) query(id << 1 | 1);  
     64     pushup(id); 
     65 }
     66 
     67 inline void out(int x)
     68 {
     69     if (x / 10) out(x / 10);
     70     putchar(x % 10 + '0');
     71 }
     72 
     73 inline void Run()
     74 {
     75     while (scanf("%d%d", &n, &m) != EOF)
     76     {
     77         memset(ans, 0, sizeof ans); sum = 0;
     78         for (int i = 1; i <= n; ++i) scanf("%d", arr + i), sum += arr[i];
     79         build(1, 1, n); remind = m; 
     80         for (int i = 1; i <= 100000; ++i, remind += m) 
     81         {
     82             if (sum == 0)
     83             {
     84                 ans[i] = ans[i - 1];
     85                 continue;
     86             }
     87             anssum = 0; query(1); 
     88             ans[i].first = ans[i - 1].first + anssum;
     89             ans[i].second = remind; 
     90         }
     91         scanf("%d", &q);
     92         for (int i = 1, x; i <= q; ++i) 
     93         {
     94             scanf("%d", &x);
     95             out(ans[x].first); putchar(' ');
     96             out(ans[x].second); putchar('
    '); 
     97         }
     98     }
     99 }
    100 
    101 int main()
    102 {
    103     #ifdef LOCAL 
    104         freopen("Test.in", "r", stdin);
    105     #endif 
    106     
    107     Run();   
    108     return 0;
    109 }
    View Code

     H. Set

    留坑。

     I. Skr

    留坑。

     J. Sum

    题意:定义$F[n] = 有多少个n = ab$ a 和 b 都不能是平方数的倍数 1 除外 求 $sum_{i = 1} ^ {i = n} F[n]$

    思路:枚举每个素数,对于拥有不同质因子的数,权值成2,对于拥有两个相同的质因子的数,权值除以2,对于拥有三个或者三个以上质因子的数,权值为零,最后求和。(卡常)

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 
     4 typedef long long ll;
     5 const int maxn = 2e7 + 5;
     6 
     7 int n;
     8 int tot;
     9 int isprime[maxn];
    10 int prime[maxn];
    11 int a[maxn];
    12 int ans[maxn];
    13 
    14 inline void Init_prime()
    15 {
    16     tot = 1;
    17     prime[1] = 1;
    18     a[1] = 1;
    19     ans[1] = 1;
    20     for (register int i = 2; i < maxn; ++i)
    21     {
    22         a[i] = 1;
    23         if (!isprime[i])
    24         {
    25             prime[tot++] = i;
    26             
    27         }
    28         for (register int j = 1; j < tot && i * prime[j] < maxn; ++j)
    29         {
    30             isprime[i * prime[j]] = 1;
    31             if (!(i % prime[j]))
    32             {
    33                 break;
    34             }
    35         }
    36     }
    37     for (register int i = 1; i < tot; ++i)
    38     {
    39         for (register int j = 1; j * prime[i] < maxn; ++j)
    40         {
    41             a[j * prime[i]] <<= 1;
    42         }
    43         if (prime[i] > maxn / prime[i]) continue;
    44         for (register int j = 1; j * prime[i] * prime[i] < maxn; ++j)
    45         {
    46             if (j % prime[i] == 0)
    47             {
    48                 a[j * prime[i] * prime[i]] = 0;
    49             }
    50             a[j * prime[i] * prime[i]] >>= 1;
    51         }
    52     }
    53     for (register int i = 1; i < maxn; ++i)
    54     {
    55         ans[i] = ans[i - 1] + a[i];
    56     }
    57 }
    58 
    59 int main()
    60 {
    61     Init_prime();
    62     int t;
    63     //cout << tot << endl;
    64     scanf("%d", &t);
    65     while (t--)
    66     {
    67         scanf("%d", &n);
    68         printf("%d
    ", ans[n]);
    69     }
    70     return 0;
    71 }
    View Code

     K. The Great Nim Game

    留坑。

     L. Magical Girl Haze

    题意:有n个城市,m条边,可以令k条路权值为0,求1 - n 的最短路

    思路:对于每个城市,枚举到这个城市,免费0-k次的权值,跑一个(立体的?)最短路

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 
      4 #define N 100010
      5 #define ll long long
      6 #define INFLL 0x3f3f3f3f3f3f3f3f
      7 
      8 struct Edge
      9 {
     10     int to, nx; ll w;
     11     inline Edge() {}
     12     inline Edge(int to, int nx, ll w) : to(to), nx(nx), w(w) {}
     13 }edge[N << 1];
     14 
     15 int head[N], pos;
     16 
     17 inline void Init()
     18 {
     19     memset(head, -1, sizeof head);
     20     pos = 0;
     21 }
     22 
     23 inline void addedge(int u, int v, ll w)
     24 {
     25     edge[++pos] = Edge(v, head[u], w); head[u] = pos;
     26 }
     27 
     28 struct node
     29 {
     30     int to, p; ll w;
     31     inline node() {}
     32     inline node(int to, int p, ll w) : to(to), p(p), w(w) {}
     33     inline bool operator < (const node &r) const
     34     {
     35         return w > r.w;
     36     }
     37 };
     38 
     39 ll dist[N][20];
     40 bool used[N][20];
     41 int t, n, m, k;
     42 
     43 inline void Dijkstra()
     44 {
     45     for (int i = 1; i <= n; ++i) for (int j = 0; j <= k; ++j) dist[i][j] = INFLL, used[i][j] = false;
     46     priority_queue <node> q; q.emplace(1, 0, 0); dist[1][0] = 0;
     47     while (!q.empty())
     48     {
     49         int u = q.top().to;
     50         int p = q.top().p;
     51         ll w = q.top().w;
     52         //cout << w << endl;
     53         q.pop();
     54         if (used[u][p]) continue;
     55         used[u][p] = true;
     56         dist[u][p] = w;
     57         for (int i = head[u]; ~i; i = edge[i].nx)
     58         {
     59             int v = edge[i].to;
     60             ll c = edge[i].w;
     61             if (dist[u][p] + c < dist[v][p])
     62             {
     63                 dist[v][p] = dist[u][p] + c;
     64                 q.emplace(v, p, dist[v][p]);
     65             }
     66             if (p + 1 <= k && dist[u][p] < dist[v][p + 1])
     67             {
     68                 dist[v][p + 1] = dist[u][p];
     69                 q.emplace(v, p + 1, dist[v][p + 1]);
     70             }
     71         }
     72     }
     73 }
     74 
     75 
     76 inline void Run()
     77 {
     78     scanf("%d", &t);
     79     while (t--)
     80     {
     81         Init();
     82         scanf("%d%d%d", &n, &m, &k);
     83         int u, v; ll w;
     84         for (int i = 1; i <= m; ++i)
     85         {
     86             scanf("%d%d%lld", &u, &v, &w);
     87             addedge(u, v, w);
     88         }
     89         Dijkstra();
     90         ll ans = dist[n][k];
     91         printf("%lld
    ", ans);
     92     }
     93 }
     94 int main()
     95 {
     96     #ifdef LOCAL
     97         freopen("Test.in", "r", stdin);
     98     #endif
     99 
    100     Run(); 
    101 
    102     return 0; 
    103 }
    View Code
  • 相关阅读:
    Java实现蓝桥杯 九宫幻方
    Java实现蓝桥杯 九宫幻方
    Java实现蓝桥杯 九宫幻方
    Java实现蓝桥杯 九宫幻方
    Java实现蓝桥杯 历届试题 合根植物
    dddd
    隋唐英雄第70集和第90集的片头真有意思
    造成远程文件大小为零的原因(索引值里变成了0)
    QDataStream类参考(串行化数据,可设置低位高位,以及版本号),还有一个例子
    房价收入比大幅攀升,已经达到足以傲视全球的境界,这已是大家的共识(好几段评论都非常精彩)
  • 原文地址:https://www.cnblogs.com/Dup4/p/9570883.html
Copyright © 2020-2023  润新知