AtCoder Beginner Contest 168
A - ∴ (Therefore)
#include <bits/stdc++.h> #define ll long long using namespace std; int main() { int n; scanf("%d", &n), n %= 10; if(n == 2 || n == 4 || n == 5 || n == 7 || n == 9) printf("hon\n"); else if(n == 0 || n == 1 || n == 6 || n == 8) printf("pon\n"); else printf("bon\n"); return 0; }
B - ... (Triple Dots)
#include <bits/stdc++.h> #define ll long long using namespace std; char s[105]; int main() { int k; scanf("%d%s", &k, s); int n = strlen(s); if(n > k) { for(int i = 0; i < k; i++) { printf("%c", s[i]); } printf("...\n"); }else { printf("%s\n", s); } return 0; }
C - : (Colon)
题意:给定时钟的时针,分针长度A,B,以及当前的时间H:M,求时针分针顶部之间的距离。
数据范围:$ 1 \leq A,B \leq 1000, 0 \leq H \leq 11, 0 \leq M \leq 59 $
题解:求出时针分针之间的角度,然后用余弦定理算出距离。
#include <bits/stdc++.h> #define ll long long using namespace std; const double PI = acos(-1.0); int main() { int a, b, h, w; scanf("%d%d%d%d", &a, &b, &h, &w); double d = fabs(30 * h - 5.5 * w); printf("%.12f\n", sqrt(a * a + b * b - 2 * cos(d / 180 * PI) * a * b)); return 0; }
D - .. (Double Dots)
题意:给一个N个点的图,M条边,在每个点设一个路标,每次只能向路标的点走,求一种方案最小化每个点到1的距离,若有点到不了1,则输出NO。
数据范围:$ 2 \leq N \leq 10^{5}, 1 \leq M \leq 2 \times 10^{5} $
题解:bfs分层,并记录每个点的父节点即可。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1e5 + 5; vector<int> G[N]; bool vis[N]; int f[N]; int main() { int n, m; scanf("%d%d", &n, &m); for(int i = 0, u, v; i < m; i++) { scanf("%d%d", &u, &v); G[u].push_back(v); G[v].push_back(u); } queue<int> qu; qu.push(1), vis[1] = true; while(!qu.empty()) { int u = qu.front(); qu.pop(); for(auto v : G[u]) { if(vis[v]) continue; f[v] = u; qu.push(v), vis[v] = true; } } bool flag = false; for(int i = 1; i <= n; i++) { if(!vis[i]) flag = true; } if(flag) { printf("No\n"); return 0; } printf("Yes\n"); for(int i = 2; i <= n; i++) { printf("%d\n", f[i]); } return 0; }
E - ∙ (Bullet)
题意:有N个物品,每个物品有A,B属性,要求取一个子集,满足子集内的任何两个物品i,j,Ai*Bj +Aj*Bi != 0,求有多少个方案数。(mod 1e9 + 7)
数据范围:$ 1 \leq N \leq 2 \times 10^{5}, -10^{18} \leq A_{i}, B_{i} \leq 10^{18} $
题解:可以将A/B看成斜率,那么问题转化成选的集合内不能有垂直的线(A = B = 0除外)。二维平面下不可能存在a垂直b,b垂直c,c垂直a的情况。
所以将物品按斜率分类,假如没有与它垂直的线,那方案数2^num次(num代表斜率为它的个数),假如有的话,2^num1- 1 + 2^num2 - 1 + 1。
A=B=0比较特殊,取了它以后,别的都不能取,所以只要加上num(A=B=0)即可,最后在减去空集的情况。
#include <bits/stdc++.h> #define ll long long using namespace std; const int MD = 1e9 + 7; map<pair<ll, ll>, int> ma; int quick_pow(int x, int y) { int ans = 1; while(y) { if(y & 1) ans = 1LL * ans * x % MD; y >>= 1; x = 1LL * x * x % MD; } return ans; } int main() { int n, s = 0; scanf("%d", &n); for(int i = 0; i < n; i++) { ll a, b; scanf("%lld%lld", &a, &b); ll d = __gcd(a, b); if(d == 0) { s++; continue; } a /= d, b /= d; if(a < 0) a = -a, b = -b; ma[{a, b}]++; } ll ans = 1; for(auto it : ma) { if(it.second == 0) continue; ll a = it.first.first, b = it.first.second; ll d = quick_pow(2, ma[{a, b}]); b = -b; if(b < 0) a = -a, b = -b; if(ma.count({b, a})) { d = (d + quick_pow(2, ma[{b, a}]) - 1) % MD; ma[{b, a}] = 0; } ans = ans * d % MD; } ans = (ans - 1 + s + MD) % MD; printf("%lld\n", ans); return 0; }
F - . (Single Dot)
题意:在二维平面内给若干个平行x轴和平行y轴的线段,不能走在线段上和穿过线段,求从(0,0)能到达的地方的面积,若为无限,输出INF。
数据范围:$ 1 \leq N, M \leq 1000, -10^{9} \leq All values \leq 10^{9} $
题解:将线段上的点离散化,然后bfs求出块面积即可,具体看代码。
#include <bits/stdc++.h> #define ll long long using namespace std; const int N = 1005; const int M = 7005; int a[N], b[N], c[N], d[N], e[N], f[N]; vector<int> vx, vy; int dx[] = {0, 0, -1, 1}, dy[] = {-1, 1, 0, 0}; bool ma[M][M], vis[M][M]; int get_x(int x) { return lower_bound(vx.begin(), vx.end(), x) - vx.begin(); } int get_y(int x) { return lower_bound(vy.begin(), vy.end(), x) - vy.begin(); } int main() { int n, m; scanf("%d%d", &n, &m); vx.push_back(-1.1e9), vx.push_back(0); vy.push_back(-1.1e9), vy.push_back(0); for(int i = 0; i < n; i++) { scanf("%d%d%d", &a[i], &b[i], &c[i]); vx.push_back(a[i]), vx.push_back(b[i]); vy.push_back(c[i]); } for(int i = 0; i < m; i++) { scanf("%d%d%d", &d[i], &e[i], &f[i]); vy.push_back(e[i]), vy.push_back(f[i]); vx.push_back(d[i]); } sort(vx.begin(), vx.end()), vx.erase(unique(vx.begin(), vx.end()), vx.end()); sort(vy.begin(), vy.end()), vy.erase(unique(vy.begin(), vy.end()), vy.end()); for(int i = 0; i < n; i++) { a[i] = get_x(a[i]), b[i] = get_x(b[i]), c[i] = get_y(c[i]); for(int j = a[i] * 2 - 1; j < 2 * b[i]; j++) { ma[j][2 * c[i] - 1] = true; } } for(int i = 0; i < m; i++) { d[i] = get_x(d[i]), e[i] = get_y(e[i]), f[i] = get_y(f[i]); for(int j = 2 * e[i] - 1; j < 2 * f[i]; j++) { ma[2 * d[i] - 1][j] = true; } } int sx = get_x(0) * 2 - 1, sy = get_y(0) * 2 - 1; bool flag = false; ll ans = 0; queue<pair<int, int>> qu; qu.push({sx, sy}), vis[sx][sy] = true; while(!qu.empty()) { int ux = qu.front().first, uy = qu.front().second; qu.pop(); if(ux == M - 1 || uy == M - 1 || ux == 0 || uy == 0) { flag = true; break; } if(ux % 2 == 0 && uy % 2 == 0) { int x = ux / 2, y = uy / 2; ans += 1LL * (vx[x + 1] - vx[x]) * (vy[y + 1] - vy[y]); } for(int i = 0 ; i < 4; i++) { int xx = ux + dx[i], yy = uy + dy[i]; if(xx >= M || xx < 0 || yy >= M || yy < 0 || vis[xx][yy] || ma[xx][yy]) continue; qu.push({xx, yy}), vis[xx][yy] = true; } } if(flag) printf("INF\n"); else printf("%lld\n", ans); return 0; }