PAT团体程序设计天梯赛 - 模拟赛
2016-05-17 00:05
615 查看
由于本人愚笨,最后一题实在无力AC,于是只有前14题的题解Orz
总的来说,这次模拟赛的题目不算难,前14题基本上一眼就有思路,但是某些题写起来确实不太容易,编码复杂度有点高~
L1-1 N个数求和
设计一个分数类,重载加法运算符,注意要约分,用欧几里得算法求个最大公约数即可。
#include <cstdio> long long abs(long long x) { return x < 0 ? -x : x; } long long gcd(long long a, long long b) { if (b == 0) return a; else if (a > b) return gcd(b, a % b); else return gcd(a, b % a); } struct FS { long long fz, fm; FS(long long _fz = 0, long long _fm = 1) { fz = _fz; fm = _fm; if (fz & fm) { long long g = gcd(abs(fz), abs(fm)); fz /= g; fm /= g; } } friend FS operator+ (const FS& a, const FS& b) { FS ans; long long lcm = a.fm / gcd(abs(a.fm), abs(b.fm)) * b.fm; ans.fz = a.fz * (lcm / a.fm) + b.fz * (lcm / b.fm); ans.fm = lcm; if (ans.fz && ans.fm) { long long g = gcd(abs(ans.fz), abs(ans.fm)); ans.fz /= g; ans.fm /= g; } return ans; } }; int main() { int n; scanf("%d", &n); FS ans; char buf[64]; while (n--) { scanf("%s", buf); long long fz, fm; sscanf(buf, "%lld/%lld", &fz, &fm); ans = ans + FS(fz, fm); } if (ans.fz == 0) printf("0"); else if (abs(ans.fz) < abs(ans.fm)) printf("%lld/%lld", ans.fz, ans.fm); else { if (ans.fz % ans.fm == 0) printf("%lld", ans.fz / ans.fm); else printf("%lld %lld/%lld", ans.fz / ans.fm, ans.fz % ans.fm, ans.fm); } return 0; }
L1-2 比较大小
太水了,不解释,直接sort一下。
#include <cstdio> #include <algorithm> using namespace std; int main() { int a[3]; scanf("%d%d%d", a, a + 1, a + 2); sort(a, a + 3); printf("%d->%d->%d", a[0], a[1], a[2]); return 0; }
L1-3 A-B
用一个bool数组记录第二个字符串中出现的字符,然后遍历第一个字符串,检测是否在第二个字符串中出现过。
#include <cstdio> #include <algorithm> using namespace std; char s1[10010]; char s2[10010]; bool vis[128]; int main() { gets(s1); gets(s2); int idx = -1; while (s2[++idx]) vis[s2[idx]] = true; idx = -1; while (s1[++idx]) if (!vis[s1[idx]]) putchar(s1[idx]); return 0; }
L1-4 计算指数
太水了,直接左移位。
#include <cstdio> #include <algorithm> using namespace std; int main() { int n; scanf("%d", &n); printf("%d^%d = %d", 2, n, 1 << n); return 0; }
L1-5 计算阶乘和
太水了,求阶乘累加。
#include <cstdio> #include <algorithm> using namespace std; int main() { int n; scanf("%d", &n); int sum = 0; int fact = 1; for (int i = 1; i <= n; i++) sum += fact *= i; printf("%d", sum); return 0; }
L1-6 简单题
hello world同级别的题。
#include <cstdio> int main() { printf("This is a simple problem."); return 0; }
L1-7 跟奥巴马一起画方块
双重循环。
#include <cstdio> #include <algorithm> using namespace std; int main() { int n; char c[2]; scanf("%d%s", &n, c); for (int i = 0; i < (n + 1) / 2; i++, puts("")) for (int j = 0; j < n; j++) putchar(c[0]); return 0; }
L1-8 查验身份证
按规则模拟就好了,注意判断前17位有无非数字。
#include <cstdio> #include <algorithm> using namespace std; int wei[] = {7,9,10,5,8,4,2,1,6,3,7,9,10,5,8,4,2}; int rlt[] = {1,0,-1,9,8,7,6,5,4,3,2}; bool check(char *s) { int sum = 0; for (int i = 0; i < 17; i++) { if (!isdigit(s[i])) return false; sum += (s[i] - '0') * wei[i]; } sum %= 11; if (rlt[sum] == -1) return s[17] == 'X'; else return s[17] - '0' == rlt[sum]; } int main() { int n; char s[20]; scanf("%d", &n); bool allpass = true; while (n--) { scanf("%s", s); if (!check(s)) { puts(s); allpass = false; } } if (allpass) puts("All passed"); return 0; }
L2-1 集合相似度
排序后,对于每个询问二分好像会超时一组数据。那么我们可以把那些数字离散化&去重之后,用hash思想来做,O(M)复杂度处理每个查询。
#include <cstdio> #include <algorithm> using namespace std; int sorted[500010]; int sset[60][10010]; bool vis[500010]; int rec[20010]; int main() { int n; scanf("%d", &n); int tot = 0; for (int i = 0; i < n; i++) { scanf("%d", &sset[i][0]); for (int j = 1; j <= sset[i][0]; j++) scanf("%d", &sset[i][j]), sorted[tot++] = sset[i][j]; sort(sset[i] + 1, sset[i] + 1 + sset[i][0]); sset[i][0] = unique(sset[i] + 1, sset[i] + 1 + sset[i][0]) - sset[i] - 1; } sort(sorted, sorted + tot); tot = unique(sorted, sorted + tot) - sorted; for (int i = 0; i < n; i++) for (int j = 1; j <= sset[i][0]; j++) sset[i][j] = lower_bound(sorted, sorted + tot, sset[i][j]) - sorted; int k; scanf("%d", &k); while (k--) { int a, b; scanf("%d%d", &a, &b); a--, b--; int nc = 0, nt = 0; int reccnt = 0; for (int i = 1; i <= sset[a][0]; i++) vis[sset[a][i]] = true, rec[reccnt++] = sset[a][i]; nt = sset[a][0]; for (int i = 1; i <= sset[b][0]; i++) { rec[reccnt++] = sset[b][i]; if (vis[sset[b][i]]) nc++; else nt++; } for (int i = 0; i < reccnt; i++) vis[rec[i]] = false; printf("%.2f%\n", 1.0 * nc / nt * 100); } return 0; }
L2-2 树的遍历
后序序列最后一个是根节点,用那个根节点把中序序列分开,然后递归建树,最后再宽搜一下。
#include <cstdio> #include <vector> #include <queue> #include <algorithm> using namespace std; vector<int> tree[40]; int n; int hx[40]; int zx[40]; int deal(int lz, int rz, int lh, int rh) { if (lz > rz || lh > rh) return -1; int root = hx[rh]; int pos = find(zx + lz, zx + rz + 1, root) - zx; int cnt = pos - lz; tree[root].push_back(deal(lz, pos - 1, lh, lh + cnt - 1)); tree[root].push_back(deal(pos + 1, rz, lh + cnt, rh - 1)); return root; } int main() { scanf("%d", &n); for (int i = 0; i < n; i++) scanf("%d", hx + i); for (int i = 0; i < n; i++) scanf("%d", zx + i); int root = deal(0, n - 1, 0, n - 1); queue<int> q; q.push(root); bool flag = false; while (!q.empty()) { int cur = q.front(); q.pop(); if (flag) printf(" %d", cur); else printf("%d", cur), flag = true; if (tree[cur][0] != -1) q.push(tree[cur][0]); if (tree[cur][1] != -1) q.push(tree[cur][1]); } return 0; }
L2-3 家庭房产
思路很简单,就是普通的并查集,但是代码不太好写哦~
#include <cstdio> #include <algorithm> using namespace std; struct Node { int parent; int ts, mj; }; struct Result { int minid; int siz; int ts, mj; friend bool operator< (const Result& a, const Result& b) { if (1LL * a.mj * b.siz == 1LL * b.mj * a.siz) return a.minid < b.minid; return 1LL * a.mj * b.siz > 1LL * b.mj * a.siz; } }; Node node[10010]; Result rlt[10010]; int uf_find(int x) { if (node[x].parent == x) return x; return node[x].parent = uf_find(node[x].parent); } void uf_union(int x, int y) { x = uf_find(x); y = uf_find(y); if (x != y) node[x].parent = y; } int main() { int n; scanf("%d", &n); for (int i = 0; i < 10000; i++) node[i].parent = i, rlt[i].minid = 1000000; while (n--) { int id, f, m, k, hz; scanf("%d%d%d%d", &id, &f, &m, &k); if (f != -1) uf_union(f, id); if (m != -1) uf_union(m, id); for (int i = 0; i < k; i++) { scanf("%d", &hz); uf_union(hz, id); } scanf("%d%d", &node[id].ts, &node[id].mj); } for (int i = 0; i < 10000; i++) { int x = uf_find(i); rlt[x].minid = min(rlt[x].minid, i); rlt[x].ts += node[i].ts; rlt[x].mj += node[i].mj; rlt[x].siz++; } sort(rlt, rlt + 10000); int cnt = 0; for (int i = 0; i < 10000; i++) { if (rlt[i].mj != 0) cnt++; else break; } printf("%d\n", cnt); for (int i = 0; i < cnt; i++) { if (rlt[i].mj != 0) printf("%04d %d %.3f %.3f\n", rlt[i].minid, rlt[i].siz, 1.0 * rlt[i].ts / rlt[i].siz, 1.0 * rlt[i].mj / rlt[i].siz); } return 0; }
L2-4 最长对称子串
枚举回文中点,向两边扩展枚举。
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; char s[1010]; int main() { gets(s); int len = strlen(s); int ans = 0; for (int i = 0; i < len; i++) { int l = i, r = i; int curans = 0; while (l >= 0 && r < len && s[l] == s[r]) curans += 2, l--, r++; ans = max(ans, curans - 1); if (i < len - 1 && s[i] == s[i + 1]) { l = i; r = l + 1; curans = 0; while (l >= 0 && r < len && s[l] == s[r]) curans += 2, l--, r++; ans = max(ans, curans); } } printf("%d", ans); return 0; }
L3-1 肿瘤诊断
三维的图找连通块,道理和二维一样,注意这里只能宽搜。
#include <cstdio> #include <queue> using namespace std; bool pic[61][1287][129]; bool vis[61][1287][129]; int dx[] = {1,-1,0,0,0,0}; int dy[] = {0,0,-1,1,0,0}; int dz[] = {0,0,0,0,1,-1}; int m, n, l, t; int bfs(int z, int x, int y) { queue<int> q; q.push(z * (m * n) + x * n + y); vis[z][x][y] = true; int cnt = 0; while (!q.empty()) { cnt++; int cur = q.front(); q.pop(); z = cur / (m * n); cur %= m * n; x = cur / n; y = cur % n; for (int i = 0; i < 6; i++) { int zz = z + dz[i]; int xx = x + dx[i]; int yy = y + dy[i]; if (zz < 0 || zz >= l) continue; if (xx < 0 || xx >= m) continue; if (yy < 0 || yy >= n) continue; if (pic[zz][xx][yy] && !vis[zz][xx][yy]) { vis[zz][xx][yy] = true; q.push(zz * (m * n) + xx * n + yy); } } } return cnt; } int main() { scanf("%d%d%d%d", &m, &n, &l, &t); for (int i = 0; i < l; i++) for (int j = 0; j < m; j++) for (int k = 0; k < n; k++) { int v; scanf("%d", &v); pic[i][j][k] = v == 1; } int ans = 0; for (int i = 0; i < l; i++) for (int j = 0; j < m; j++) for (int k = 0; k < n; k++) { if (!vis[i][j][k] && pic[i][j][k]) { int cnt = bfs(i, j, k); if (cnt >= t) ans += cnt; } } printf("%d", ans); return 0; }
L3-2 垃圾箱分布
跑m次spfa就好了,注意结果四舍五入~
#include <cstdio> #include <vector> #include <queue> #include <algorithm> using namespace std; const long long inf = 1LL << 62; vector<pair<int, int> > G[1020]; long long dis[1020]; bool inqueue[1020]; int n, m, k; long long ds; long long ansdis = -1; double avgdis = 1e30; int ansid = -1; void spfa(int s) { fill(dis, dis + 1020, inf); queue<int> q; q.push(s); dis[s] = 0; while (!q.empty()) { int cur = q.front(); q.pop(); inqueue[cur] = false; for (int i = 0; i < G[cur].size(); i++) { if (dis[cur] + G[cur][i].second < dis[G[cur][i].first]) { dis[G[cur][i].first] = dis[cur] + G[cur][i].second; if (!inqueue[G[cur][i].first]) { inqueue[G[cur][i].first] = true; q.push(G[cur][i].first); } } } } long long mindis = *min_element(dis + 1, dis + n + 1); long long maxdis = *max_element(dis + 1, dis + n + 1); if (maxdis > ds) return; double sum = 0.0; for (int i = 1; i <= n; i++) sum += dis[i]; sum /= n; if (mindis > ansdis) { ansdis = mindis; avgdis = sum; ansid = s; } else if (mindis == ansdis) { if (avgdis - sum > 1e-9) { ansdis = mindis; avgdis = sum; ansid = s; } } } int main() { scanf("%d%d%d%lld", &n, &m, &k ,&ds); for (int i = 0; i < k; i++) { char s1[10], s2[10]; int a, b, d; scanf("%s%s%d", s1, s2, &d); if (s1[0] == 'G') sscanf(s1 + 1, "%d", &a), a += n; else sscanf(s1, "%d", &a); if (s2[0] == 'G') sscanf(s2 + 1, "%d", &b), b += n; else sscanf(s2, "%d", &b); G[a].push_back(make_pair(b, d)); G[b].push_back(make_pair(a, d)); } for (int i = n + 1; i <= n + m; i++) spfa(i); if (ansid == -1) puts("No Solution"); else { avgdis *= 10.0; avgdis += 0.5; avgdis = floor(avgdis); avgdis /= 10.0; printf("G%d\n%.1lf %.1lf", ansid - n, 1.0 * ansdis, avgdis); } return 0; }
L1-1 | N个数求和 | |
L1-2 | 比较大小 | |
L1-3 | A-B | |
L1-4 | 计算指数 | |
L1-5 | 计算阶乘和 | |
L1-6 | 简单题 | |
L1-7 | 跟奥巴马一起画方块 | |
L1-8 | 查验身份证 | |
L2-1 | 集合相似度 | |
L2-2 | 树的遍历 | |
L2-3 | 家庭房产 | |
L2-4 | 最长对称子串 | |
L3-1 | 肿瘤诊断 | |
L3-2 | 垃圾箱分布 |
相关文章推荐
- Linux下提示命令找不到:bash:command not found
- 在ASP.NET 2.0中操作数据之五十三:在Data Web控件显示二进制数据
- 在ASP.NET 2.0中操作数据之五十四:添加新记录时包含一个文件上传选项
- 在ASP.NET 2.0中操作数据之五十五:编辑和删除现有的二进制数据
- android在service中播放音乐
- 在ASP.NET 2.0中操作数据之五十六:使用ObjectDataSource缓存数据
- 在ASP.NET 2.0中操作数据之五十七:在分层架构中缓存数据
- 在ASP.NET 2.0中操作数据之五十八:在程序启动阶段缓存数据
- 在ASP.NET 2.0中操作数据之五十九:使用SQL缓存依赖项SqlCacheDependency
- Win7下搭建python开发环境图文教程(安装Python、pip、解释器)
- Windows下搭建python开发环境详细步骤
- Windows下Eclipse+PyDev配置Python+PyQt4开发环境
- 图文详解WinPE下安装Python
- python采用django框架实现支付宝即时到帐接口
- python模拟Django框架实例
- python中list列表的高级函数
- python实现汉诺塔递归算法经典案例
- Yii2如何批量添加数据
- CI框架中redis缓存相关操作文件示例代码
- CI框架中数据库操作函数$this->db->where()相关用法总结