C. ZOJ3983 暴力;
#include <bits/stdc++.h> using namespace std; #define db long double #define int long long #define eps 0.00000001 #define maxn 500000 #define INF 999999999.99999 int mark[4], a[10]; string s; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * k; } signed main() { int T = read(); while(T --) { string s; cin >> s; for(int i = 0; i < 9; i ++) if(s[i] == 'a') a[i + 1] = 1; else if(s[i] == 'o') a[i + 1] = 2; else a[i + 1] = 3; for(int i = 1; i <= 3; i ++) mark[i] = 0; for(int i = 1; i <= 9; i ++) if(!mark[a[i]]) mark[a[i]] = i; int flag = 0; for(int i = 1; i <= 3; i ++) { for(int j = 2; j < 9; j ++) if(a[j] == i && a[j - 1] == i && a[j + 1] == i) flag = j; if(flag) { int num = 0; bool flag2 = 0; for(int k = 1; k <= 3; k ++) { if(k == i) continue; num = 0; for(int m = mark[k]; m <= 9; m ++) if(a[m] == i) continue; else if(a[m] == k) num ++; else break; if(num == 3) { flag2 = 1; break; } } if(!flag2) printf("2 "); else printf("3 "); break; } } if(!flag) { bool flag2 = 0; for(int i = 1; i <= 3; i ++) { int num = 0; for(int j = 1; j <= 3; j ++) { if(j == i) continue; num = 0; for(int k = mark[j]; k <= 9; k ++) { if(a[k] == j) num ++; else if(a[k] == i) continue; else break; } if(num == 3) flag2 = 1; } } if(flag2) printf("2 "); else printf("1 "); } } return 0; }
D. ZOJ3984
由于构造图的性质,可以发现最后一个加入的点一定会与图中所有的点有连边。若删去该点,则剩下的各个连通块也仍然满足该性质。如果一个连通块中不存在满足此要求的点,则说明无法构造出这张图。所以只需要逐个找到这样的点判断其度数是否与当前连通块中点的个数-1相等即可。
将点的度数从大到小排序,则删去一个点后对仍在同一连通块中的所有点产生的影响相同即度数减一,所以不会影响点之间的度数相对大小,故只要按这个顺序删点判断。由于删点顺序已知,所以将删点改为倒序加点,并查集动态查询连通块中点的个数进行判断。
#include <bits/stdc++.h> using namespace std; #define maxn 1000000 #define pb push_back int n, m, fa[maxn], size[maxn]; vector <int> ans[maxn]; bool mark[maxn]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * k; } struct node { int id, d; friend bool operator <(node a, node b) { return a.d < b.d; } }p[maxn]; struct edge { int head[maxn], last[maxn], to[maxn], cnp = 1; void add(int u, int v) { to[cnp] = v, last[cnp] = head[u], head[u] = cnp ++; to[cnp] = u, last[cnp] = head[v], head[v] = cnp ++; } }E; void init() { for(int i = 1; i <= n; i ++) p[i].d = mark[i] = 0; for(int i = 1; i <= n; i ++) E.head[i] = 0; for(int i = 1; i <= n; i ++) ans[i].clear(); for(int i = 1; i <= n; i ++) fa[i] = i, size[i] = 1; } int find(int u) { if(u == fa[u]) return u; return fa[u] = find(fa[u]); } void Merge(int u, int v) { u = find(u), v = find(v); fa[u] = v, size[v] += size[u]; } int main() { int T = read(); while(T --) { n = read(), m = read(); bool flag = 1; init(); for(int i = 1; i <= m; i ++) { int u = read(), v = read(); E.add(u, v); p[u].d ++, p[v].d ++; } for(int i = 1; i <= n; i ++) p[i].id = i; sort(p + 1, p + 1 + n); for(int i = 1; i <= n; i ++) { int u = p[i].id, cnt = 0; mark[u] = 1; for(int j = E.head[u]; j; j = E.last[j]) { int v = E.to[j]; if(!mark[v]) continue; cnt ++; if(find(u) != find(v)) Merge(find(u), find(v)), ans[i].pb(v); } if(cnt != size[find(u)] - 1) { flag = 0; break; } } if(!flag) printf("No "); else { printf("Yes "); for(int i = 1; i <= n; i ++) { printf("%d %d", p[i].id, ans[i].size()); for(auto it = ans[i].begin(); it != ans[i].end(); it ++) printf(" %d", *it); printf(" "); } } } return 0; }
E.ZOJ3985 暴力;
#include <bits/stdc++.h> using namespace std; #define maxn 1000000 int ans, mark[maxn], rec[maxn]; string S, S1, S2; int main() { int T; cin >> T; S = "CCPC"; S1 = "CCPCPC"; S2 = "CCPCPC"; while(T --) { int n; cin >> n; ans = 0; string s; cin >> s; for(int i = 0; i < n; i ++) { bool flag = 1; for(int j = 0; j < 4; j ++) if(s[i + j] == S[j]) continue; else { flag = 0; break; } mark[i] = flag; if(flag) ans ++; if(flag) i += 2; } for(int i = -1; i < n; i ++) { bool flag = 1; for(int j = i - 2; j <= i; j ++) if(j >= 0 && mark[j]) { flag = 0; break; } if(!flag) continue; flag = 0; for(int j = 0; j < 4; j ++) { int num = 0; for(int k = i - j + 1; k >= 0 && k <= i - j + 3; k ++) { if(num == j) num ++; if(s[k] == S[num]) num ++; else break; } if(j == 3 && num == 3) flag = 1; else if(num == 4) flag = 1; } if(flag) { if(i >= 0) rec[i] = 1; else rec[n] = 1; } flag = 0; int num = 0; for(int j = i - 2; j >= 0 && j < n && j <= i + 3; j ++) if(s[j] == S1[num]) { num ++; } if(num == 6) flag = 1; num = 0; for(int j = i - 2; j >= 0 && j < n && j <= i + 3; j ++) if(s[j] == S2[num]) num ++; if(num == 6) flag = 1; if(flag) rec[i] = 2; } bool f1 = 0, f2 = 0; for(int i = 0; i <= n; i ++) { if(rec[i] == 1 && !f1) f1 = 1, ans += 1; else if(rec[2] == 2 && !f2) f2 = 1, ans += 2; } if(!(f1 + f2)) printf("%d ", ans); else if(f1 + f2 == 1) printf("%d ", ans); else printf("%d ", ans - 1); for(int i = 0; i <= n; i ++) mark[i] = rec[i] = 0; } }
G.ZOJ 3987
从高位向低位贪心,如果一位上能不放一则不放,否则则尽量多放。需要写高精度或者利用java bigint。高精度取模:n % m : 设 n = k * m + t;则可以对 k 进行二进制分解,保证在 log 的复杂度内完成。
#include <bits/stdc++.h> using namespace std; #define maxn 50000 #define maxm 1110 char s[maxn]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * k; } struct num { int d[maxm], l; void init() { l = 0; memset(d, 0, sizeof(d)); } void div() { for(int i = l; i >= 0; i --) { if(i > 0 && d[i] & 1) d[i - 1] += 10; d[i] /= 2; } for(int i = l; i >= 0; i --) if(d[i]) { l = i; break; } else if(!d[i] && !i) l = i; } friend bool operator <(num a, num b) { if(a.l != b.l) return a.l < b.l; for(int i = a.l; i >= 0; i --) if(a.d[i] < b.d[i]) return 1; else if(a.d[i] > b.d[i]) return 0; return 0; } friend num operator +(num a, num b) { num c; c.init(); if(a.l < b.l) swap(a, b); for(int i = a.l; i >= 0; i --) c.d[i] = a.d[i] + b.d[i]; for(int i = 0; i <= a.l; i ++) if(c.d[i] >= 10) c.d[i + 1] += c.d[i] / 10, c.d[i] %= 10; c.l = a.l; if(c.d[c.l + 1]) c.l ++; return c; } friend num operator *(num a, num b) { num c; c.init(); c.l = a.l + b.l; if(a.l < b.l) swap(a, b); for(int i = 0; i <= b.l; i ++) for(int j = 0; j <= a.l; j ++) c.d[i + j] += a.d[j] * b.d[i]; for(int i = 0; ; i ++) { c.d[i + 1] += c.d[i] / 10; c.d[i] = c.d[i] % 10; if(i > a.l + b.l) c.l = i; if(i > a.l + b.l && !c.d[i + 1]) break; } for(int i = c.l; i >= 0; i --) if(c.d[i]) { c.l = i; break; } else if(!c.d[i] && !i) c.l = 0; return c; } friend num operator -(num a, num b) { num c; c.init(); for(int i = 0; i <= a.l; i ++) { if(a.d[i] >= b.d[i]) c.d[i] = a.d[i] - b.d[i]; else c.d[i] = a.d[i] + 10 - b.d[i], a.d[i + 1] -= 1; } c.l = a.l; for(int i = c.l; i >= 0; i --) if(c.d[i]) { c.l = i; break; } else if(!c.d[i] && i == 0) c.l = i; return c; } friend num operator %(num a, num b) { num base = b; while(b < a) b = b + b; b.div(); for(; !(b < base); ) { while(!(a < b)) a = a - b; b.div(); } return a; } void read() { memset(d, 0, sizeof(d)); scanf("%s", &s); l = strlen(s) - 1; for(int i = 0; i <= l; i ++) d[i] = s[l - i] - '0'; } void pt() { for(int i = l; i >= 0; i --) printf("%d", d[i]); cout << endl; } }; int main() { int T = read(); num one, ans; one.l = 0, one.d[0] = 1; while(T --) { num n, m; n.read(), m.read(); ans.init(); num base; base.init(); base.d[0] = 2; int rec; for(int k = 0; ; k ++, base = base + base) if(!(m * (base - one) < n)) { rec = k; break; } base.div(); num tem; for(int k = rec; k >= 0; k --, base.div()) { if(!(m * (base - one) < n)) continue; num tem = m * base; if(!(n < tem)) n = n - tem; else n = (n % base); ans = ans + base; } ans.pt(); } return 0; }
M. ZOJ 3993
需要注意的是虽然 r <= R 一定成立,但 R - r >= r 不一定成立,注意判断的细节。
#include <bits/stdc++.h> using namespace std; #define db long double #define int long long #define eps 0.00000001 #define maxn 500000 #define INF 999999999.99999 int dis[maxn], st[maxn]; db fdis[maxn]; int read() { int x = 0, k = 1; char c; c = getchar(); while(c < '0' || c > '9') { if(c == '-') k = -1; c = getchar(); } while(c >= '0' && c <= '9') x = x * 10 + c - '0', c = getchar(); return x * k; } bool big(db a, db b) { if(a - b >= 0) return 1; return 0; } bool eq(db a, db b) { if(a == b) return 1; return 0; } bool sm(db a, db b) { if(a - b < 0) return 1; return 0; } signed main() { int T = read(); while(T --) { int n = read(), R = read(), r = read(), num = 0; R -= r; for(int i = 1; i <= n; i ++) { int x = read(), y = read(); dis[i] = x * x + y * y; fdis[i] = sqrt((db) dis[i]); } db mind = INF; for(int i = 1; i <= n; i ++) { if(R >= r && big(((db) R) - mind, (db) r) && big(((db) R) - fdis[i], (db) r)) { num ++, st[num] = i; } else if(R < r && big(((db) r) - mind, (db) R) && big(((db) r) - fdis[i], (db) R)) { num ++, st[num] = i; } else if(sm(fdis[i], mind)) { mind = fdis[i], num = 1, st[num] = i; } else if(eq(fdis[i], mind)) { num ++, st[num] = i; } } printf("%lld ", num); for(int i = 1; i < num; i ++) printf("%lld ", st[i]); printf("%lld ", st[num]); } return 0; }