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", 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\n", 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:\n", 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\n", 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\n", 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\n", 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('\n'); 
 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\n", 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\n", 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

 

转载于:https://www.cnblogs.com/Dup4/p/9570883.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值