广东工业大学第12届ACM程序设计大赛部分题解
来源:互联网 发布:arm服务器 知乎 编辑:程序博客网 时间:2024/06/06 15:10
A
#include <cstdio>#include <cmath>#include <cstring>#include <sstream>#include <iostream>#include <algorithm>#include <queue>#include <stack>#include <string>#include <vector>#include <map>#include <set>#include <utility> using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define mst(Arr, x) memset(Arr, x, sizeof(Arr))#define REP(i, x, n) for(int i = x; i < n; ++i)const int qq = 1e5 + 10;const int INF = 1e9 + 10;int n, m; int main(){ int t; scanf("%d", &t); while(t--){ int a, b, c; scanf("%d%d%d", &a, &b, &c); int num = c / 4; int x = num - b; int y = num - a / 2; printf("%d\n", num - x - y); } return 0;} /************************************************************** Problem: 1224 User: Yokile Language: C++ Result: Accepted Time:0 ms Memory:1696 kb****************************************************************/
B
参考官方题解:
令 d = abs(x1-x2)+abs(y1-y2)首先判断(n+1)/2 >= d,先手可不可以从一个点走到另一个点 :
如果不可以,则先手可以多得 n&1 分(因为劣势者可以选择逃离)
如果可以,考虑 d 的奇偶性:如果 d 为奇数(先手可以先踩到后手覆盖过的点):
如果 n 为奇数,先手可以多得 2 分,否则平。否则(d 为偶数)
:如果 n 为奇数,先手可以多得 1 分,否则后手可以多得 1 分。
#include <cstdio>#include <cmath>#include <cstring>using namespace std;#define LL long longint main(){int t;scanf("%d", &t);while(t--){LL n, x1, x2, y1, y2;scanf("%lld%lld%lld%lld%lld", &n, &x1, &y1, &x2, &y2);LL d = abs(x1 - x2) + abs(y1 - y2);LL ans = -1;if((n + 1) / 2 >= d){if(d % 2 == 0){ans = 1;}else{if(n & 1)ans = 2;}}else if(n & 1){ans = 1;}printf("%lld\n", ans);}return 0;}
这题还是不难的,- - 、果然还是萌新阿
C
这题也就是简单地递推, 然后乘法原理即可
#include <cstdio>#include <cmath>#include <cstring>#include <sstream>#include <iostream>#include <algorithm>#include <queue>#include <stack>#include <string>#include <vector>#include <map>#include <set>#include <utility> using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define mst(Arr, x) memset(Arr, x, sizeof(Arr))#define REP(i, x, n) for(int i = x; i < n; ++i)const int qq = 1e5 + 10;const int INF = 1e9 + 10;const int MOD = 10007;int n;LL dp[30]; int main(){ dp[0] = 0, dp[1] = 1, dp[2] = 2, dp[3] = 4; for(int i = 4; i <= 20; ++i) dp[i] = dp[i - 1] + dp[i - 2] + dp[i - 3]; int t; scanf("%d", &t); while(t--){ scanf("%d", &n); LL tot = 1; REP(i, 1, n){ int x; scanf("%d", &x); tot = (tot * dp[x]) % MOD; } printf("%lld\n", tot); } return 0;} /************************************************************** Problem: 1226 User: Yokile Language: C++ Result: Accepted Time:0 ms Memory:1696 kb****************************************************************/
D
#include <cstdio>#include <cmath>#include <cstring>#include <sstream>#include <iostream>#include <algorithm>#include <queue>#include <stack>#include <string>#include <vector>#include <map>#include <set>#include <utility> using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define mst(Arr, x) memset(Arr, x, sizeof(Arr))#define REP(i, x, n) for(int i = x; i < n; ++i)const int qq = 1e5 + 10;const int INF = 1e9 + 10;int n, m; int main(){ int t; scanf("%d", &t); while(t--){ LL a, b, c; scanf("%lld%lld%lld", &a, &b, &c); LL sum = a * b; sum = sum + (a / 10 / 3) * c; printf("%lld\n", sum); } return 0;} /************************************************************** Problem: 1227 User: Yokile Language: C++ Result: Accepted Time:0 ms Memory:0 kb****************************************************************/
E
这题貌似标程除了问题 题目还需要重判,但我觉得我的算法没啥问题
首先要尽可能的缩小瓶子数目,不断除2, 但是当瓶子数目为奇数时就会剩下一瓶,这时候这瓶水就要独立出来,放入一个集合中
最后这个集合进行操作, 首先要明确, 如果你有一瓶x升的水, 这个水一定是2^n, 不会是别的数了, 如果队列中不存在另外一个x,那么就必须补充x瓶水
因为每次都是对最小的进行操作,所以最后求出来肯定是最小的
#include <cstdio>#include <cmath>#include <cstring>#include <sstream>#include <iostream>#include <algorithm>#include <queue>#include <stack>#include <string>#include <vector>#include <map>#include <set>#include <utility>using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define mst(Arr, x) memset(Arr, x, sizeof(Arr))#define REP(i, x, n) for(int i = x; i < n; ++i)const int qq = 1e5 + 10;const int INF = 1e9 + 10;int n, m, k;int main(){ int t; scanf("%d", &t); while(t--){ priority_queue<int, vector<int>, greater<int> > Q; scanf("%d%d", &n, &k); int t = 1; while(n){ if(n & 1) Q.push(t); n /= 2; t <<= 1; } LL minx = 0; while((int)Q.size() > k){ int x = Q.top(); Q.pop(); int y = Q.top(); Q.pop(); if(x == y){ Q.push(x + y); }else{ minx += x; Q.push(x + x); Q.push(y); } } printf("%lld\n", minx); } return 0;}
F
Tarjan离线求出最近公共祖先, 然后求这条路径上所有线段的长度, 然后排一次序, 然后每三个相邻的数判断一下能不能形成三角形
没给时间限制, 就暴力做了, 没想到还过了。。。。
昨天学长教我这题的正确解题姿势, 线段的长度都在1到1e9内, 我们可以这样想,假设三条线段a,b,c,令a<=b=<c, 如果满足a + b > c那么一定是个三角形,那么不满足的极限条件就是a + b = c, 换一种说法,就是在区间1到1e9内选择尽量多的数,使得选择出来的任意三个数都不能组成三角形, 这样推出来的结论就是这些选择出来的数满足菲波那契数列, 然后就可以根据路径的长度进行剪枝了,最终的复杂度还是O(m + q)。学长说好像是2016年大连区域赛的一道题也是这样剪的
#include <cstdio>#include <cmath>#include <cstring>#include <sstream>#include <iostream>#include <algorithm>#include <queue>#include <stack>#include <string>#include <vector>#include <map>#include <set>#include <utility> using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define mst(Arr, x) memset(Arr, x, sizeof(Arr))#define REP(i, x, n) for(int i = x; i < n; ++i)const int qq = 1e5 + 10;const int INF = 1e9 + 10;int n, m, top;int fa[qq], pre[qq], head[qq], plen[qq], anc[qq];int num[qq];int l[qq], r[qq];bool vis[qq];struct Edge{ int v, next, w;}edge[qq * 2];vector<int> q[qq], f[qq];void Add(int u, int v, int w){ edge[top].v = v; edge[top].w = w; edge[top].next = head[u]; head[u] = top++;}void Init(){ mst(head, -1); mst(vis, false); mst(plen, 0); mst(anc, 0); top = 0; for(int i = 0; i <= n; ++i) q[i].clear(), f[i].clear(); }int Find(int x){ return fa[x] == -1 ? x : fa[x] = Find(fa[x]);}void Union(int x, int y){ int b = Find(y); if(x != b) fa[b] = x;}void Tarjan(int u, int p, int w){ fa[u] = pre[u] = -1; for(int i = head[u]; i != -1; i = edge[i].next){ int v = edge[i].v; if(v == p || vis[v]) continue; Tarjan(v, u, edge[i].w); Union(u, v); } vis[u] = true; pre[u] = p; plen[u] = w; for(int i = 0; i < (int)q[u].size(); ++i)if(vis[q[u][i]]){ anc[f[u][i]] = Find(q[u][i]); }}bool check(int c, int b, int a){ if(a + b > c && a + c > b && b + c > a) return true; return false;} int main(){ int t; scanf("%d", &t); while(t--){ Init(); scanf("%d", &n); REP(i, 1, n){ int a, b, c; scanf("%d%d%d", &a, &b, &c); Add(a, b, c); Add(b, a, c); } int m; scanf("%d", &m); REP(i, 0, m){ int a, b;scanf("%d%d", &a, &b); l[i] = a, r[i] = b; q[a].pb(b), f[a].pb(i); q[b].pb(a), f[b].pb(i); } Tarjan(1, -1, 0); /*for(int i = 0; i < m; ++i){ printf("%d\n", anc[i]); }*/ REP(i, 0, m){ int cnt = 0; int u = l[i]; int v = anc[i]; while(u != v){ num[cnt++] = plen[u]; u = pre[u]; } u = r[i]; while(u != v){ num[cnt++] = plen[u]; u = pre[u]; } sort(num, num + cnt); bool flag = false; for(int j = 2; j < cnt; ++j){ if(check(num[j], num[j - 1], num[j - 2])){ flag = true; break; } } if(flag) puts("Yes"); else puts("No"); } } return 0;} /************************************************************** Problem: 1229 User: Yokile Language: C++ Result: Accepted Time:104 ms Memory:11964 kb****************************************************************/
H
这题有个很显然的结论,你如果能凑出区间[0, x],那么对于一个数p,如果x + 1 >= p, 那么你就能凑出区间[0,x + p]的所有数
这题有个加强版的 传送门
#include <cstdio>#include <cmath>#include <cstring>#include <sstream>#include <iostream>#include <algorithm>#include <queue>#include <stack>#include <string>#include <vector>#include <map>#include <set>#include <utility> using namespace std;#define LL long long#define pb push_back#define mk make_pair#define pill pair<int, int>#define mst(Arr, x) memset(Arr, x, sizeof(Arr))#define REP(i, x, n) for(int i = x; i < n; ++i)const int qq = 1e5 + 10;const int INF = 1e9 + 10;int n, m;LL num[qq]; int main(){ int t; scanf("%d", &t); while(t--){ scanf("%d", &n); REP(i, 0, n){ scanf("%lld", num + i); } LL money = 0; sort(num, num + n); REP(i, 0, n){ if(num[i] <= money + 1){ money += num[i]; }else{ break; } } printf("%lld\n", money); } return 0;} /************************************************************** Problem: 1231 User: Yokile Language: C++ Result: Accepted Time:0 ms Memory:0 kb****************************************************************/
- 广东工业大学第12届ACM程序设计大赛部分题解
- 广东工业大学第12届ACM程序设计大赛 Problem H: tmk买礼物
- 广东工业大学第12届ACM程序设计大赛 Problem E: 倒水(Water)
- 广东工业大学第12届ACM程序设计大赛 Problem C: 爬楼梯
- 广东工业大学第12届ACM程序设计大赛 Problem A: 两只老虎
- 广东工业大学第12届ACM程序设计大赛 Problem D: 只有通过毁灭才能揭示真理
- 河南省第三届ACM程序设计大赛题解
- 第三届河南省程序设计大赛 - 部分题解
- 第四届河南省程序设计大赛 - 部分题解
- 2015年福州大学第12届程序设计大赛题解
- 第10届 “新秀杯” ACM程序设计大赛网络预选赛 部分代码~
- 第九届 北邮程序设计大赛网络赛 部分题解
- 第四届“图灵杯”NEUQ-ACM程序设计竞赛部分题解
- 大连海事大学2017ACM程序设计大赛题解
- 2015广东工业大学新生赛 总结+部分题解
- 南京理工大学第八届程序设计大赛题解
- 第八届Nuist程序设计大赛 题解
- 计信院程序设计大赛题解
- Caffe源码解读(二):caffe.proto(下)
- Floyd-Warshall算法模板
- 灰度投影法和余弦定理用于阵列图像分类
- 慕课网学习笔记----《网页布局基础》—绝对定位布局
- Android事件分发机制源码分析下----ViewGroup事件分发分析
- 广东工业大学第12届ACM程序设计大赛部分题解
- Canvas实现简易圆形进度条
- ConcurrentLinkedQueue
- patL1-002. 打印沙漏
- LeetCode算法题——19. Remove Nth Node From End of List
- Java序列化以及其实现机制
- CPP_Basic_Summary_0.3
- shell基础-bash基本功能-输入输出重定向
- ubuntu16.0.4 下搜狗输入法安装及输入中文时乱码解决