HNOI2014解题报告
来源:互联网 发布:诸暨行知小学怎么样 编辑:程序博客网 时间:2024/05/21 00:48
HNOI2014解题报告
Author: Pengyihao
Day1 T1 画框
思路
这个题目我其实是没有思路的。
网上说要用一种高深的最小乘积生成树的算法,我就学了一下。
我们把每一种搭配方案中,
那么一种搭配方案就可以看做一个坐标
因为
因为反比例函数越靠近原点,
所以我们要
找到
为什么大家都用KM算法,就我用费用流?好怕怕啊
然后我们就要找到在这两个方案的坐标的连线的下方,且三个方案形成的三角形面积最大的方案。
这个面积用叉积可以计算,最后发现形如
于是我们可以再跑一遍费用流求出这个方案
递归处理
边界就是
这个据说递归次数期望是
代码
#include <bits/stdc++.h>typedef long long LL;#define FOR(i, a, b) for (LL i = (a), i##_END_ = (b); i <= i##_END_; i++)#define DNF(i, a, b) for (LL i = (a), i##_END_ = (b); i >= i##_END_; i--)template <typename Tp> void in(Tp &x) { char ch = getchar(); x = 0; while (ch < '0' || ch > '9') ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();}template <typename Tp> Tp Min(Tp x, Tp y) {return x < y ? x : y;}template <typename Tp> Tp Max(Tp x, Tp y) {return x > y ? x : y;}template <typename Tp> Tp chkmax(Tp &x, Tp y) {return x > y ? x : x=y;}template <typename Tp> Tp chkmin(Tp &x, Tp y) {return x < y ? x : x=y;}const LL MAXN = 80;LL n, A[MAXN][MAXN], B[MAXN][MAXN], tmp[MAXN][MAXN];namespace KM{ using std::queue; queue<LL>q; bool in_stack[MAXN << 1]; const LL ss = 0, tt = 159; LL cnt, ret1, ret2, dis[MAXN << 1], pre[MAXN << 1]; LL head[MAXN << 1], data[MAXN * MAXN << 2], flow[MAXN * MAXN << 2]; LL wei1[MAXN * MAXN << 2], wei2[MAXN * MAXN << 2], nxt[MAXN * MAXN << 2], wei[MAXN * MAXN << 2]; void add(LL x, LL y, LL z, LL l, LL l1, LL l2) { nxt[cnt] = head[x]; data[cnt] = y; flow[cnt] = z; wei[cnt] = l; wei1[cnt] = l1; wei2[cnt] = l2; head[x] = cnt++; nxt[cnt] = head[y]; data[cnt] = x; flow[cnt] = 0; wei[cnt] =-l; wei1[cnt] =-l1; wei2[cnt] =-l2; head[y] = cnt++; } bool bfs() { memset(pre, -1, sizeof pre); memset(dis, 0x3f, sizeof dis); dis[ss] = 0; q.push(ss); in_stack[ss] = true; while (!q.empty()) { LL now = q.front(); q.pop(); in_stack[now] = false; for (LL i = head[now]; i != -1; i = nxt[i]) { if (flow[i] && dis[data[i]] > dis[now] + wei[i]) { dis[data[i]] = dis[now] + wei[i]; pre[data[i]] = i; if (!in_stack[data[i]]) { in_stack[data[i]] = true; q.push(data[i]); } } } } return pre[tt] != -1; } void dfs() { for (LL i = tt; pre[i] != -1; i = data[pre[i] ^ 1]) ret1 += wei1[pre[i]]; for (LL i = tt; pre[i] != -1; i = data[pre[i] ^ 1]) ret2 += wei2[pre[i]]; for (LL i = tt; pre[i] != -1; i = data[pre[i] ^ 1]) flow[pre[i]]--, flow[pre[i] ^ 1]++; } std::pair<LL, LL>main(LL argv[MAXN][MAXN]) { ret1 = ret2 = 0; cnt = 0; memset(head, -1, sizeof head); FOR(i, 1, n) add(ss, i, 1, 0, 0, 0); FOR(i, 1, n) FOR(j, 1, n) { add(i, j + n, 1, argv[i][j], A[i][j], B[i][j]); } FOR(i, 1, n) add(i + n, tt, 1, 0, 0, 0); while (bfs()) dfs(); return std::make_pair(ret1, ret2); }}bool gongxian(std::pair<LL, LL>l, std::pair<LL, LL>mid, std::pair<LL, LL>r){ return (l.second - r.second) * (l.first - mid.first) == (l.second - mid.second) * (l.first - r.first);}LL get_ans(std::pair<LL, LL>l, std::pair<LL, LL>r){ if (l.first == r.first || l.second == r.second) return Min(l.first * l.second, r.first * r.second); FOR(i, 1, n) FOR(j, 1, n) tmp[i][j] = -((r.second - l.second) * A[i][j] + (l.first - r.first) * B[i][j]); std::pair<LL, LL>mid = KM::main(tmp); if (gongxian(l, mid, r)) return Min(l.first * l.second, r.first * r.second); return Min(get_ans(l, mid), get_ans(mid, r));}int main(){ freopen("frame.in", "r", stdin); freopen("frame.out", "w", stdout); LL tcase; in(tcase); while (tcase--) { in(n); FOR(i, 1, n) FOR(j, 1, n) in(A[i][j]); FOR(i, 1, n) FOR(j, 1, n) in(B[i][j]); std::pair<LL, LL>retA = KM::main(A), retB = KM::main(B); printf("%lld\n", get_ans(retA, retB)); } return 0;}
Day1 T2 世界树
思路
这也是我没学过的算法——虚树。
首先用单调栈维护右链,把虚树构建出来;
然后对于虚树上的每条边,把它的分界点找出来,然后分段赋给管理端点的那两个点。
注意判断管理端点的两个点相同的情况。
这个题目的构建虚树需要用lca,我用了倍增。
这个题目找到分界点也需要用倍增。
没有使用数据结构,代码却比数据结构题还要长。
代码
#include <bits/stdc++.h>typedef long long LL;#define debug(...) fprintf(stderr, __VA_ARGS__)#define FOR(i, a, b) for (int i = (a), i##_END_ = (b); i <= i##_END_; i++)#define DNF(i, a, b) for (int i = (a), i##_END_ = (b); i >= i##_END_; i--)template <typename Tp> void in(Tp &x) { char ch = getchar(); x = 0; while (ch < '0' || ch > '9') ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar();}template <typename Tp> Tp Min(Tp x, Tp y) {return x < y ? x : y;}template <typename Tp> Tp Max(Tp x, Tp y) {return x > y ? x : y;}template <typename Tp> Tp chkmax(Tp &x, Tp y) {return x > y ? x : x=y;}template <typename Tp> Tp chkmin(Tp &x, Tp y) {return x < y ? x : x=y;}const int MAXN = 300010;bool is_chs[MAXN];int n, q, num[MAXN], fa[MAXN], dfn[MAXN], sa[MAXN], depth[MAXN], sz[MAXN];int INDEX, cnt, head[MAXN], data[MAXN << 1], nxt[MAXN << 1], log_num[1000010];int anc[MAXN][20], xsz[MAXN], val[MAXN];void add(int x, int y){ nxt[cnt] = head[x]; data[cnt] = y; head[x] = cnt++; nxt[cnt] = head[y]; data[cnt] = x; head[y] = cnt++;}void dfs(int now, int pa){ sz[now] = 1; depth[now] = depth[pa] + 1; fa[now] = pa; dfn[now] = ++INDEX; for (int i = head[now]; i != -1; i = nxt[i]) { if (data[i] != pa) { dfs(data[i], now); sz[now] += sz[data[i]]; } }}void dfs_anc(int now, int pa){ anc[now][0] = pa; for (int i = 1; anc[now][i - 1] != -1; i++) { anc[now][i] = anc[anc[now][i - 1]][i - 1]; } for (int i = head[now]; i != -1; i = nxt[i]) { if (data[i] != pa) dfs_anc(data[i], now); }}namespace get_lca{ int eula[MAXN * 3], st[MAXN], ed[MAXN], IND, to[MAXN]; int minx[MAXN * 3][21]; void dfs2(int now) { eula[++eula[0]] = ++IND; st[now] = eula[0]; to[IND] = now; for (int i = head[now]; i != -1; i = nxt[i]) { if (data[i] != fa[now]) { dfs2(data[i]); eula[++eula[0]] = eula[st[now]]; } } ed[now] = eula[0]; } int lca(int x, int y) { if (!x || !y) return 0; if (st[x] > ed[y]) std::swap(x, y); x = st[x]; y = ed[y]; int delta = log_num[y - x + 1]; return to[Min(minx[x][delta], minx[y - (1 << delta) + 1][delta])]; } void start() { FOR(i, 1, eula[0]) minx[i][0] = eula[i]; FOR(i, 1, 20) { FOR(j, 1, eula[0]) { if (j + (1 << i) - 1 > eula[0]) break; minx[j][i] = Min(minx[j][i - 1], minx[j + (1 << (i - 1))][i - 1]); } } FOR(i, 1, 1000000) log_num[i] = log2(i); }}int stack[MAXN], top, in_tree[MAXN];int head_xu[MAXN], cnt_xu, nxt_xu[MAXN << 1], data_xu[MAXN << 1];namespace build_tree{ void add_xu(int x, int y) { nxt_xu[cnt_xu] = head_xu[x]; data_xu[cnt_xu] = y; head_xu[x] = cnt_xu++; nxt_xu[cnt_xu] = head_xu[y]; data_xu[cnt_xu] = x; head_xu[y] = cnt_xu++; } bool cmp(int x, int y) { return dfn[x] < dfn[y]; } void builds_tree() { cnt_xu = 0; stack[top = 1] = 0; in_tree[0] = 0; FOR(i, 1, num[0]) { is_chs[num[i]] = true; in_tree[++in_tree[0]] = num[i]; } in_tree[++in_tree[0]] = 0; std::sort(in_tree + 1, in_tree + in_tree[0] + 1, cmp); int now_in_tree = in_tree[0]; FOR(i, 2, now_in_tree) { int now = in_tree[i]; int anc = get_lca::lca(stack[top], now); if (anc == stack[top]) stack[++top] = now; else { while (true) { int tp = stack[top], tp_l = stack[top - 1]; if (tp_l == anc) { add_xu(tp_l, tp); top--; break; } else if (dfn[tp_l] > dfn[anc]) { add_xu(tp_l, tp); top--; } else { in_tree[++in_tree[0]] = anc; add_xu(anc, tp); stack[top] = anc; break; } } stack[++top] = now; } } while (top != 1) { add_xu(stack[top - 1], stack[top]); top--; } }}namespace find_father{ int find(int x, int y) { for (int i = 19; i >= 0; i--) { if (y & (1 << i)) { x = anc[x][i]; } } return x; }}namespace DP{ int f[MAXN][2], g[MAXN][2], ret[MAXN]; void dp1(int now, int pa) { val[now] = 0; xsz[now] = 1; f[now][0] = is_chs[now] ? 0 : 0x3f3f3f3f; f[now][1] = now; for (int i = head_xu[now]; i != -1; i = nxt_xu[i]) { if (data_xu[i] != pa) { dp1(data_xu[i], now); xsz[now] += xsz[data_xu[i]]; int frm = depth[data_xu[i]] - depth[now]; if (f[now][0] > f[data_xu[i]][0] + frm || f[now][0] == f[data_xu[i]][0] + frm && f[now][1] > f[data_xu[i]][1]) { f[now][1] = f[data_xu[i]][1]; f[now][0] = f[data_xu[i]][0] + frm; } } } } void dp2(int now, int pa) { g[now][0] = f[now][0]; g[now][1] = f[now][1]; if (pa != -1) { int frm = depth[now] - depth[pa]; if (g[now][0] > g[pa][0] + frm || g[now][0] == g[pa][0] + frm && g[now][1] > g[pa][1]) { g[now][1] = g[pa][1]; g[now][0] = g[pa][0] + frm; } } for (int i = head_xu[now]; i != -1; i = nxt_xu[i]) { if (data_xu[i] != pa) dp2(data_xu[i], now); } } int getr(int x, int y, int z, bool t) { if (y - x + z < 0) return 0; if (t) return (y - x + z) / 2; else { if ((y - x + z) % 2 == 0) return (y - x + z) / 2; else return (y - x + z) / 2 + 1; } } void dp3(int now, int pa) { if (!pa) { ret[g[now][1]] += n - sz[now]; } bool flag = false; for (int i = head_xu[now]; i != -1; i = nxt_xu[i]) if (data_xu[i] != pa) { flag = true; int nnum = data_xu[i], all; if (now) { all = depth[nnum] - depth[now] - 1; if (g[now][1] == g[nnum][1]) { if (all) { int pos = find_father::find(nnum, all); ret[g[now][1]] += sz[pos] - sz[nnum]; val[now] -= sz[pos]; } else val[now] -= sz[nnum]; } else {// ret[g[now][1]] += getr(g[now][0], g[nnum][0], all,// g[now][1] > g[nnum][1]);// ret[g[nnum][1]] += getr(g[nnum][0], g[now][0], all,// g[nnum][1] > g[now][1]); if (!all) { val[now] -= sz[nnum]; } else { int Anc = getr(g[nnum][0], g[now][0], all, g[nnum][1] > g[now][1]); int pos = find_father::find(nnum, Anc); ret[g[nnum][1]] += sz[pos] - sz[nnum]; int pos2 = find_father::find(nnum, all); ret[g[now][1]] += sz[pos2] - sz[pos]; val[now] -= sz[pos2]; } } } dp3(nnum, now); } } void dp4(int now, int pa) { if (now) ret[g[now][1]] += sz[now] + val[now]; for (int i = head_xu[now]; i != -1; i = nxt_xu[i]) { if (data_xu[i] != pa) dp4(data_xu[i], now); } } void work() { build_tree::builds_tree(); FOR(i, 1, num[0]) ret[num[i]] = 0; dp1(0, -1); dp2(0, -1); dp3(0, -1); dp4(0, -1); FOR(i, 1, num[0]) printf("%d ", ret[num[i]]); putchar(10); }}int main(){ freopen("worldtree.in", "r", stdin); freopen("worldtree.out", "w", stdout); memset(head, -1, sizeof head); memset(head_xu, -1, sizeof head_xu); in(n); FOR(i, 1, n - 1) { int x, y; in(x); in(y); add(x, y); } memset(anc, -1, sizeof anc); dfs(1, 0); dfs_anc(1, 0); get_lca::dfs2(1); get_lca::start(); FOR(i, 1, n) sa[dfn[i]] = i; in(q); FOR(i, 1, q) { FOR(i, 1, num[0]) is_chs[num[i]] = false; FOR(i, 1, in_tree[0]) head_xu[in_tree[i]] = -1; in(num[0]); FOR(j, 1, num[0]) in(num[j]); DP::work(); } return 0;}
Day1 T3 米特运输
思路
根据每个点的权值,计算出根节点的权值。
然后用
因为数据太大,所以需要取对数。
代码
#include <bits/stdc++.h>typedef long long LL;#define FOR(i, a, b) for (int i = (a), i##_END_ = (b); i <= i##_END_; i++)#define DNF(i, a, b) for (int i = (a), i##_END_ = (b); i >= i##_END_; i--)template <typename Tp> void in(Tp &x) { char ch = getchar(), f = 1; x = 0; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= f;}template <typename Tp> Tp chkmax(Tp &x, Tp y) {return x > y ? x : x=y;}template <typename Tp> Tp chkmin(Tp &x, Tp y) {return x < y ? x : x=y;}template <typename Tp> Tp Max(Tp x, Tp y) {return x > y ? x : y;}template <typename Tp> Tp Min(Tp x, Tp y) {return x < y ? x : y;}const int MAXN = 500010;long double rot[MAXN], val[MAXN];int n, w[MAXN], tot[MAXN];int cnt, head[MAXN], data[MAXN << 1], nxt[MAXN << 1];void add(int x, int y){ nxt[cnt] = head[x]; data[cnt] = y; head[x] = cnt++; nxt[cnt] = head[y]; data[cnt] = x; head[y] = cnt++;}void dfs1(int now, int pa){ for (int i = head[now]; i != -1; i = nxt[i]) if (data[i] != pa) { tot[now]++; dfs1(data[i], now); }}void dfs2(int now, int pa){ for (int i = head[now]; i != -1; i = nxt[i]) { if (data[i] != pa) { val[data[i]] = log(tot[now]) + val[now]; dfs2(data[i], now); } }}const long double eps = 1e-6;int main(){ freopen("meat.in", "r", stdin); freopen("meat.out", "w", stdout); memset(head, -1, sizeof head); in(n); FOR(i, 1, n) in(w[i]); FOR(i, 1, n - 1) {int u, v; in(u); in(v); add(u, v);} dfs1(1, 0); dfs2(1, 0); FOR(i, 1, n) rot[i] = val[i] + log(w[i]); std::sort(rot + 1, rot + n + 1); int ret = 0, line = 0; FOR(i, 1, n) { if (i == 1 || fabs(rot[i] - rot[i - 1]) > eps) { chkmax(ret, line); line = 1; } else line++; } chkmax(ret, line); printf("%d\n", n - ret); return 0;}
Day2 T1 抄卡组
思路
首先,如果所有的字符串都有通配符,那么只需要两两比较前缀和后缀即可。
就是按每个字符串不包含通配符的最大前缀长度进行排序,比较一遍;
然后按每个字符串不包含通配符的最大后缀长度进行排序,比较一边。
如果所有的字符串都没有通配符,那么只需要比较hash值就可以了。
如果有些有通配符,有些没有通配符,将没有通配符的进行比较,看是否相同。
然后对于有通配符的,将通配符视作分隔符,即把原串分为一段一段的,分开进行匹配。
注意有通配符的字符串和没有通配符的字符串的首尾要对应。
代码
#include <bits/stdc++.h>typedef long long LL;typedef unsigned long long ULL;#define FOR(i, a, b) for (int i = (a), i##_END_ = (b); i <= i##_END_; i++)#define DNF(i, a, b) for (int i = (a), i##_END_ = (b); i >= i##_END_; i--)template <typename Tp> void in(Tp &x) { char ch = getchar(), f = 1; x = 0; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= f;}template <typename Tp> Tp chkmax(Tp &x, Tp y) {return x > y ? x : x=y;}template <typename Tp> Tp chkmin(Tp &x, Tp y) {return x < y ? x : x=y;}template <typename Tp> Tp Max(Tp x, Tp y) {return x > y ? x : y;}template <typename Tp> Tp Min(Tp x, Tp y) {return x < y ? x : y;}const int MAXN = 2000010;using std::string;using std::cin;using std::cout;string str[MAXN];int t, n, len[MAXN];ULL hs[MAXN];const ULL BASE = 31;int prefix[MAXN], suffix[MAXN], numb[MAXN];void gethash(int num){ hs[num] = 0; FOR(i, 0, len[num] - 1) { hs[num] = hs[num] * BASE + str[num][i]; }}bool isop[MAXN];int nopera[MAXN];ULL rhs[MAXN], po[MAXN];ULL power(ULL x, ULL y){ if (!y) return 1; return po[y];}void work(){ string *a = str; FOR(i, 1, nopera[0]) isop[nopera[i]] = false; nopera[0] = 0; FOR(i, 1, n) { bool flag = true; FOR(j, 0, len[i] - 1) { if (str[i][j] == '*') { flag = false; break; } } if (flag) { isop[i] = true; nopera[++nopera[0]] = i; } } FOR(i, 2, nopera[0]) { if (hs[nopera[i]] != hs[nopera[i - 1]]) { puts("N"); return; } } int need_compare = nopera[1]; ULL TBASE = 1; FOR(i, 1, len[need_compare]) { rhs[i] = rhs[i - 1] + str[need_compare][i - 1] * TBASE; TBASE = TBASE * BASE; } FOR(i, 1, n) if (!isop[i]) { int lastpos = 0; for (int j = 0, k; j <= len[i] - 1; j = k + 1) { k = j; while (k < len[i] && str[i][k] == '*') k++; j = k; while (k < len[i] && str[i][k] != '*') k++; k--; if (str[i][k] == '*') break; ULL nowhs = 0, TBASE = 1; FOR(l, j, k) { nowhs = nowhs + str[i][l] * TBASE; TBASE = TBASE * BASE; } while (true) { if (lastpos + (k - j + 1) > len[need_compare]) { puts("N"); return; } if (k == len[i] - 1) { lastpos = len[need_compare] - (k - j + 1); } ULL tmpnow = nowhs; if (rhs[lastpos + (k - j + 1)] - rhs[lastpos] == tmpnow * power(31, lastpos)) { lastpos += (k - j + 1); break; } if (j != 0) { lastpos++; } else { puts("N"); return; } } } } puts("Y");}bool cmp_prefix(int x, int y){ return prefix[x] < prefix[y];}bool cmp_suffix(int x, int y){ return suffix[x] < suffix[y];}int main(){ freopen("hs.in", "r", stdin); freopen("hs.out", "w", stdout); po[0] = 1; FOR(i, 1, 2000000) po[i] = po[i - 1] * BASE; std::ios::sync_with_stdio(false); cin >> t; while (t--) { cin >> n; FOR(i, 1, n) cin >> str[i], len[i] = str[i].size(); bool isy = true, isn = true; FOR(i, 1, n) { gethash(i); bool iss = false; FOR(j, 0, len[i] - 1) { if (str[i][j] == '*') isn = false, iss = true; } if (!iss) isy = false; } if (isn) { bool flag = false; FOR(i, 2, n) if (hs[i] != hs[i - 1]) { flag = true; break; } if (!flag) puts("Y"); else puts("N"); continue; } else if (isy) { FOR(i, 1, n) { FOR(j, 0, len[i] - 1) { if (str[i][j] == '*') { prefix[i] = j; break; } } DNF(j, len[i] - 1, 0) { if (str[i][j] == '*') { suffix[i] = len[i] - 1 - j; break; } } } bool flag = true; FOR(i, 1, n) numb[i] = i; std::sort(numb + 1, numb + n + 1, cmp_prefix); FOR(i, 2, n) { int last = numb[i - 1], now = numb[i]; FOR(j, 1, prefix[last]) { if (str[last][j - 1] != str[now][j - 1]) { flag = false; puts("N"); break; } } if (!flag) break; } if (!flag) continue; std::sort(numb + 1, numb + n + 1, cmp_suffix); FOR(i, 2, n) { int last = numb[i - 1], now = numb[i]; FOR(j, 1, suffix[last]) { if (str[last][len[last] - j] != str[now][len[now] - j]) { flag = false; puts("N"); break; } } if (!flag) break; } if (flag) puts("Y"); continue; } else { work(); } } return 0;}
Day2 T2 道路堵塞
这是一道玄学题,需要依赖splay的复杂度的不确定性进行解题。
所以我跳过了它。
Day2 T3 江南乐
思路
首先用SG函数就可以做到
然后因为这题是分石子,我们可以发现分出来的石子很多都是一样的。
其实只可能分出两种石子,大小为
根据数量的奇偶性,最终会被消成不超过两个。
因为只关注奇偶性,所以对于
复杂度为
代码
#include <bits/stdc++.h>typedef long long LL;#define FOR(i, a, b) for (int i = (a), i##_END_ = (b); i <= i##_END_; i++)#define DNF(i, a, b) for (int i = (a), i##_END_ = (b); i >= i##_END_; i--)template <typename Tp> void in(Tp &x) { char ch = getchar(), f = 1; x = 0; while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar(); if (ch == '-') f = -1, ch = getchar(); while (ch >= '0' && ch <= '9') x = x * 10 + ch - '0', ch = getchar(); x *= f;}template <typename Tp> Tp chkmax(Tp &x, Tp y) {return x > y ? x : x=y;}template <typename Tp> Tp chkmin(Tp &x, Tp y) {return x < y ? x : x=y;}template <typename Tp> Tp Max(Tp x, Tp y) {return x > y ? x : y;}template <typename Tp> Tp Min(Tp x, Tp y) {return x < y ? x : y;}const int MAXN = 100010;int t, f, sg[MAXN], can[MAXN];int main(){ freopen("game.in", "r", stdin); freopen("game.out", "w", stdout); in(t); in(f); FOR(i, 0, f - 1) sg[i] = 0; FOR(i, f, 100000) { for (int j = 2, k; j <= i; j = k + 1) { k = i / (i / j); int s1 = j, s2 = j + 1; int a = ((i % s1) & 1) ? (i / s1 + 1) : 0; int b = ((s1 - (i % s1)) & 1) ? (i / s1) : 0; can[sg[a] ^ sg[b]] = i; a = ((i % s2) & 1) ? (i / s2 + 1) : 0; b = ((s2 - (i % s2)) & 1) ? (i / s2) : 0; can[sg[a] ^ sg[b]] = i; } FOR(j, 0, 100000) if (can[j] != i) { sg[i] = j; break; } } FOR(i, 1, t) { int n, ret = 0; in(n); FOR(j, 1, n) { int x; in(x); ret ^= sg[x]; } if (ret) printf("1"); else printf("0"); if (i != t) printf(" "); } return 0;}
- HNOI2014解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- 解题报告
- Antiprime解题报告
- expr解题报告
- 华容道解题报告
- tju解题报告
- zju1062/pku1095解题报告
- UsacoGate解题报告 --- 序曲
- ZJU 2060 解题报告
- ZJU 1331 解题报告
- ZJU 1115 解题报告
- ZJU1057解题报告
- c++作业6
- 输入adb shell 时 提示error: more than one device and emulator
- Unity3d
- HNOI2012解题报告
- 大日志文件中如何统计单词个数?及map按value排序lambda表达式版
- HNOI2014解题报告
- PHP日期和时间设置时区
- HNOI2015解题报告
- 51Nod-1574-排列转换
- ubuntu+vim+opencv+cmake环境搭建
- MATLAB学习笔记
- HNOI2017总结
- 抽象类和接口的相同点和不同点,学习笔记
- 『ORACLE』 约束实验(11g)