2014ACM/ICPC亚洲区鞍山赛区现场赛——题目重现
2014ACM/ICPC亚洲区鞍山赛区现场赛——题目重现
5小时内就搞了5题B、C、D、E,I。
H题想到要打表搞了,可惜时间不够,后面打出表试了几下过了- -
K题过的人也比較多。感觉是个几何旋转+ploya。可是几何实在不行没什么想法
B:这题就是一个大模拟,直接数组去模拟就可以。注意细节就能过
C:类似大白上一题红蓝三角形的。 每一个数字找一个互质和一个不互质个数。除掉反复就直接除2,然后总的C(n, 3)减去就可以,问题在怎么处理一个数字互质和不互质的,事实上仅仅要处理出不互质的就可以。这步利用容斥原理去搞。每一个数字分解成因子,然后计数因子个数。对于每一个数而言,为f(1个质因子) - f(2个质因子) + f(3) - f(4) + ...,然后就能够统计出答案了
D:这题首先转化成n个数字去掉k个,惯性最小。那么事实上重心的计算方法。就依据物理里面的杠杆原理(反正我是这样想的),因为质量都是1。所以等于全部距离累加起来。然后减去0。在除个数就是等于每一个位置距离中心要降低的长度。那么推出公式∑(di−d平均值)2,事实上这个就是方差了,问题就转化为n个数字去掉k个,使得方差最大,那么贪心知道越密集越好,所以肯定是连续的n - k个。那么仅仅要从左往右一遍扫过去不断维护就可以
E:dp,dp[i][j]表示到第i个位置,在第j列,这样递推过去就可以。也算比較水的一题
H:把竖的一列看成一个二进制数,每次就相当与选已有的两个二进制数。去构造一个新的二进制数,然后把这个数丢进已有的数组中。没想到好的办法,写个暴力,让他跑9步(这个跑了1分多钟。10步的话要跑好久啊),然后发现还有6个无解,全赋为10就wa了。然后试了一下,原来有一个解的答案是11。然后就过了- -
I:这题就是个签到题,不能多说
K:应该是几何旋转求出有几种方式,然后ploya定理求解
代码:
B:
#include <cstdio> #include <cstring> #include <map> using namespace std; typedef long long ll; const int N = 5005; int t, n, x; char op[15]; int top, a[N], an; map<int, ll> C; void init() { C.clear(); top = 0; an = 0; } int find(int u) { for (int i = 0; i < an; i++) if (a[i] == u) return i; } void Add() { scanf("%d", &x); if (C.count(x)) printf("same priority.\n"); else { C[x] = 0; a[an++] = x; printf("success.\n"); } } void Close() { scanf("%d", &x); if (!C.count(x)) printf("invalid priority.\n"); else { printf("close %d with %I64d.\n", x, C[x]); C.erase(x); int tmp = find(x); an--; for (int i = tmp; i < an; i++) a[i] = a[i + 1]; } } void Chat() { scanf("%d", &x); if (an == 0) printf("empty.\n"); else { if (top) C[top] += x; else C[a[0]] += x; printf("success.\n"); } } void Rotate() { scanf("%d", &x); if (x >= 1 && x <= an) { int tmp = a[x - 1]; for (int i = x - 1; i; i--) a[i] = a[i - 1]; a[0] = tmp; printf("success.\n"); } else printf("out of range.\n"); } void Prior() { if (an == 0) printf("empty.\n"); else { int Max = 0, Max_v; for (int i = 0; i < an; i++) { if (Max < a[i]) Max = a[i], Max_v = i; } int tmp = a[Max_v]; for (int i = Max_v; i; i--) a[i] = a[i - 1]; a[0] = tmp; printf("success.\n"); } } void Choose() { scanf("%d", &x); if (C.count(x)) { int v = find(x); int tmp = a[v]; for (int i = v; i; i--) a[i] = a[i - 1]; a[0] = tmp; printf("success.\n"); } else printf("invalid priority.\n"); } void Top() { scanf("%d", &x); if (C.count(x)) { top = x; printf("success.\n"); } else printf("invalid priority.\n"); } void Untop() { if (top == 0) printf("no such person.\n"); else { top = 0; printf("success.\n"); } } void gao() { if (top && C[top]) printf("Bye %d: %I64d\n", top, C[top]); for (int i = 0; i < an; i++) { if (a[i] == top) continue; if (C[a[i]] == 0) continue; printf("Bye %d: %I64d\n", a[i], C[a[i]]); } } int main() { scanf("%d", &t); while (t--) { init(); scanf("%d", &n); for (int i = 1; i <= n; i++) { scanf("%s", op); printf("Operation #%d: ", i); if (!strcmp(op, "Add")) Add(); if (!strcmp(op, "Close")) Close(); if (!strcmp(op, "Chat")) Chat(); if (!strcmp(op, "Rotate")) Rotate(); if (!strcmp(op, "Prior")) Prior(); if (!strcmp(op, "Choose")) Choose(); if (!strcmp(op, "Top")) Top(); if (!strcmp(op, "Untop")) Untop(); } gao(); } return 0; }
C:
#include <cstdio> #include <cstring> #include <vector> using namespace std; typedef long long ll; const int N = 100005; int vis[N], prime[N], pn = 0; void getprime() { for (int i = 2; i < N; i++) { if (vis[i]) continue; prime[pn++] = i; for (ll j = (ll)i * i; j < N; j += i) vis[j] = 1; } } int fac[N], fn; void getfac(int n) { fn = 0; if (n == 1) { fac[fn++] = 1; return; } int tmp = n; for (int i = 0; i < pn && prime[i] * prime[i] <= tmp; i++) { if (tmp % prime[i] == 0) { fac[fn++] = prime[i]; while (tmp % prime[i] == 0) tmp /= prime[i]; } } if (tmp != 1) fac[fn++] = tmp; } vector<int> g[N]; int cnt[N]; void dfs(int n, int u, int sum, int c) { if (u == fn) { if (c == 0) return; g[n].push_back(sum); cnt[sum] = c; return; } dfs(n, u + 1, sum * fac[u], c + 1); dfs(n, u + 1, sum, c); } void build(int n) { getfac(n); dfs(n, 0, 1, 0); } void init() { getprime(); for (int i = 1; i <= 100000; i++) build(i); } int t, n, a[N]; int have[N]; int main() { init(); scanf("%d", &t); while (t--) { scanf("%d", &n); memset(have, 0, sizeof(have)); for (int i = 0; i < n; i++) { scanf("%d", &a[i]); for (int j = 0; j < g[a[i]].size(); j++) have[g[a[i]][j]]++; } ll ans = (ll)n * (n - 1) * (n - 2) / 6; ll cao = 0; for (int i = 0; i < n; i++) { ll sb = 0; for (int j = 0; j < g[a[i]].size(); j++) { int facc = g[a[i]][j]; if (cnt[facc] % 2) sb += have[facc]; else sb -= have[facc]; } cao += (sb - 1) * (n - sb); } printf("%I64d\n", ans - cao / 2); } return 0; }
D:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int N = 50005; int t, n, k; double a[N]; int main() { scanf("%d", &t); while (t--) { scanf("%d%d", &n, &k); for (int i = 0; i < n; i++) scanf("%lf", &a[i]); if (n == k) { printf("%.10lf\n", 0.0); continue; } sort(a, a + n); k = n - k; double s1 = 0, s2 = 0; for (int i = 0; i < k; i++) s2 += a[i]; for (int i = 0; i < k; i++) s1 += a[i] * a[i]; double ans = s1 - s2 * s2 / k * 2 + s2 * s2 / k; for (int i = k; i < n; i++) { s1 = s1 - a[i - k] * a[i - k] + a[i] * a[i]; s2 = s2 - a[i - k] + a[i]; ans = min(ans, s1 - s2 * s2 / k * 2 + s2 * s2 / k); } printf("%.10lf\n", ans); } return 0; }
E:
#include <cstdio> #include <cstring> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int N = 55; int t, n, m; int g[N][N], dp[N * 2][N], a; int main() { scanf("%d", &t); while (t--) { scanf("%d%d", &n, &m); for (int i = 1; i <= m; i++) for (int j = 1; j <= m; j++) scanf("%d", &g[i][j]); memset(dp, -INF, sizeof(dp)); scanf("%d", &a); if (a == -1) for (int i = 1; i <= m; i++) dp[1][i] = 0; else dp[1][a] = 0; int ans = 0; for (int i = 2; i <= n; i++) { scanf("%d", &a); int s, e; if (a == -1) s = 1, e = m; else s = a, e = a; for (int j = s; j <= e; j++) { for (int k = 1; k <= m; k++) dp[i][j] = max(dp[i][j], dp[i - 1][k] + g[k][j]); if (i == n) ans = max(dp[i][j], ans); } } printf("%d\n", ans); } return 0; }
H:
打表程序:
#include <cstdio> #include <cstring> #include <set> #include <vector> using namespace std; const int INF = 0x3f3f3f3f; const int N = 105; int ans[1005]; int h[N], hn = 0; int NAND(int a, int b) { return (~(a&b))&((1<<8) - 1); } vector<int> ss; int vis[257]; void dfs(int step) { ans[h[hn - 1]] = min(ans[h[hn - 1]], step); if (step == 9) return; int v[257]; memset(v, 0, sizeof(v)); for (int i = 0; i < hn; i++) { for (int j = i; j < hn ;j++) { int tmp = NAND(h[i], h[j]); if (v[tmp]) continue; v[tmp] = 1; if (vis[tmp]) continue; h[hn++] = tmp; vis[tmp] = 1; dfs(step + 1); vis[tmp] = 0; hn--; } } } int main() { memset(ans, INF, sizeof(ans)); vis[240] = vis[204] = vis[170] = vis[255] = vis[0] = 1; h[hn++] = 240; h[hn++] = 204; h[hn++] = 170; h[hn++] = 255; h[hn++] = 0; ans[240] = ans[204] = ans[170] = ans[255] = ans[0] = 1; dfs(1); for (int i = 0; i < 256; i++) printf("sb[%d] = %d;\n", i, ans[i]); return 0; }
表:
#include <cstdio> #include <cstring> const int INF = 0x3f3f3f3f; int t; char str[10]; int sb[300]; int main() { sb[0] = 1; sb[1] = 8; sb[2] = 7; sb[3] = 5; sb[4] = 7; sb[5] = 5; sb[6] = 8; sb[7] = 5; sb[8] = 6; sb[9] = 9; sb[10] = 4; sb[11] = 6; sb[12] = 4; sb[13] = 6; sb[14] = 5; sb[15] = 2; sb[16] = 7; sb[17] = 5; sb[18] = 8; sb[19] = 5; sb[20] = 8; sb[21] = 5; sb[22] = 11;//就这个是11- -,也就是说假设能优化到跑10步,事实上答案就显而易见了 sb[23] = 8; sb[24] = 8; sb[25] = 7; sb[26] = 8; sb[27] = 6; sb[28] = 8; sb[29] = 6; sb[30] = 8; sb[31] = 5; sb[32] = 6; sb[33] = 9; sb[34] = 4; sb[35] = 6; sb[36] = 8; sb[37] = 7; sb[38] = 8; sb[39] = 6; sb[40] = 7; sb[41] = 1061109567; sb[42] = 4; sb[43] = 7; sb[44] = 7; sb[45] = 7; sb[46] = 5; sb[47] = 4; sb[48] = 4; sb[49] = 6; sb[50] = 5; sb[51] = 2; sb[52] = 8; sb[53] = 6; sb[54] = 8; sb[55] = 5; sb[56] = 7; sb[57] = 7; sb[58] = 5; sb[59] = 4; sb[60] = 5; sb[61] = 7; sb[62] = 8; sb[63] = 2; sb[64] = 6; sb[65] = 9; sb[66] = 8; sb[67] = 7; sb[68] = 4; sb[69] = 6; sb[70] = 8; sb[71] = 6; sb[72] = 7; sb[73] = 1061109567; sb[74] = 7; sb[75] = 7; sb[76] = 4; sb[77] = 7; sb[78] = 5; sb[79] = 4; sb[80] = 4; sb[81] = 6; sb[82] = 8; sb[83] = 6; sb[84] = 5; sb[85] = 2; sb[86] = 8; sb[87] = 5; sb[88] = 7; sb[89] = 7; sb[90] = 5; sb[91] = 7; sb[92] = 5; sb[93] = 4; sb[94] = 8; sb[95] = 2; sb[96] = 7; sb[97] = 1061109567; sb[98] = 7; sb[99] = 7; sb[100] = 7; sb[101] = 7; sb[102] = 5; sb[103] = 7; sb[104] = 9; sb[105] = 1061109567; sb[106] = 7; sb[107] = 9; sb[108] = 7; sb[109] = 9; sb[110] = 6; sb[111] = 7; sb[112] = 4; sb[113] = 7; sb[114] = 5; sb[115] = 4; sb[116] = 5; sb[117] = 4; sb[118] = 8; sb[119] = 2; sb[120] = 7; sb[121] = 9; sb[122] = 6; sb[123] = 7; sb[124] = 6; sb[125] = 7; sb[126] = 8; sb[127] = 4; sb[128] = 5; sb[129] = 9; sb[130] = 8; sb[131] = 7; sb[132] = 8; sb[133] = 7; sb[134] = 9; sb[135] = 6; sb[136] = 3; sb[137] = 9; sb[138] = 5; sb[139] = 6; sb[140] = 5; sb[141] = 6; sb[142] = 6; sb[143] = 3; sb[144] = 8; sb[145] = 7; sb[146] = 9; sb[147] = 6; sb[148] = 9; sb[149] = 6; sb[150] = 9; sb[151] = 9; sb[152] = 8; sb[153] = 6; sb[154] = 8; sb[155] = 6; sb[156] = 8; sb[157] = 6; sb[158] = 9; sb[159] = 6; sb[160] = 3; sb[161] = 9; sb[162] = 5; sb[163] = 6; sb[164] = 8; sb[165] = 6; sb[166] = 8; sb[167] = 6; sb[168] = 4; sb[169] = 9; sb[170] = 1; sb[171] = 6; sb[172] = 5; sb[173] = 7; sb[174] = 5; sb[175] = 3; sb[176] = 5; sb[177] = 6; sb[178] = 6; sb[179] = 3; sb[180] = 8; sb[181] = 6; sb[182] = 9; sb[183] = 6; sb[184] = 5; sb[185] = 7; sb[186] = 5; sb[187] = 3; sb[188] = 7; sb[189] = 7; sb[190] = 8; sb[191] = 5; sb[192] = 3; sb[193] = 9; sb[194] = 8; sb[195] = 6; sb[196] = 5; sb[197] = 6; sb[198] = 8; sb[199] = 6; sb[200] = 4; sb[201] = 9; sb[202] = 5; sb[203] = 7; sb[204] = 1; sb[205] = 6; sb[206] = 5; sb[207] = 3; sb[208] = 5; sb[209] = 6; sb[210] = 8; sb[211] = 6; sb[212] = 6; sb[213] = 3; sb[214] = 9; sb[215] = 6; sb[216] = 5; sb[217] = 7; sb[218] = 7; sb[219] = 7; sb[220] = 5; sb[221] = 3; sb[222] = 8; sb[223] = 5; sb[224] = 4; sb[225] = 9; sb[226] = 5; sb[227] = 7; sb[228] = 5; sb[229] = 7; sb[230] = 7; sb[231] = 7; sb[232] = 7; sb[233] = 1061109567; sb[234] = 4; sb[235] = 7; sb[236] = 4; sb[237] = 7; sb[238] = 4; sb[239] = 6; sb[240] = 1; sb[241] = 6; sb[242] = 5; sb[243] = 3; sb[244] = 5; sb[245] = 3; sb[246] = 8; sb[247] = 5; sb[248] = 4; sb[249] = 7; sb[250] = 4; sb[251] = 6; sb[252] = 4; sb[253] = 6; sb[254] = 7; sb[255] = 1; scanf("%d", &t); while (t--) { scanf("%s", str); int ans = 0; for (int i = 7; i >= 0; i--) ans = ans * 2 + str[i] - '0'; int out = sb[ans]; if (out == INF) out = 10; printf("%d\n", out); } return 0; }
I:
#include <cstdio> #include <cstring> #include <cmath> #include <algorithm> using namespace std; int t, n; const int N = 1005; struct Point { double x, y; int t; void read() { scanf("%d%lf%lf", &t, &x, &y); } } p[N]; bool cmp(Point a, Point b) { return a.t < b.t; } double dis(Point a, Point b) { double dx = a.x - b.x; double dy = a.y - b.y; return sqrt(dx * dx + dy * dy); } int main() { scanf("%d", &t); while (t--) { scanf("%d", &n); for (int i = 0; i < n; i++) { p[i].read(); } sort(p, p + n, cmp); double ans = 0; for (int i = 1; i < n; i++) { ans = max(ans, dis(p[i], p[i - 1]) / (p[i].t - p[i - 1].t)); } printf("%.10lf\n", ans); } return 0; }
H:事后补