@qq290637843
2021-05-09T11:42:19.000000Z
字数 23178
阅读 445
题目见https://www.jisuanke.com/contest/12755/challenges。
先解决没有回溯要求的问题。由于要求能删点,所以并查集的写法要加一些虚点,让实点绝对不会成为父节点,而只有实点才会被删除,所以就保证了算法的正确性。
接着,先把操作离线,得到一个版本树,于是就是在这棵树上深度优先搜索,然后可持久化数组。因为该问题实际是用三个数组维护并查集,所以就是对该三数组的版本信息保存,存法就是数组中每个元素实际上是一个栈。本题空间要求比较死,所以用前向链表实现栈。
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul maxm = 1e6;const ul maxn = 1e6;class node {public:ul next = 0;ul val = 0;};ul tot = 0;ul remain = 0;node nodes[4 * maxn + 6 * maxm + 1];ul stack[4 * maxn + 6 * maxm + 1];void push_front(ul& a, ul b){ul tmp;if (remain) {tmp = stack[remain];--remain;} else {++tot;tmp = tot;}nodes[tmp].next = a;nodes[tmp].val = b;a = tmp;}void pop_front(ul& a){++remain;stack[remain] = a;a = nodes[a].next;}ul n, m;ul query(const ul v[], ul index){return nodes[v[index]].val;}void change(ul v[], ul index, ul val, ul& changes){push_front(v[index], val);push_front(changes, index);}ul op[maxm + 1];ul k[maxm + 1];ul a[maxm + 1];ul b[maxm + 1];ul fa[maxn + maxn + 1];ul rk[maxn + 1];ul sz[maxn + 1];ul sons[maxm + 1];ul ans[maxm + 1];ul getfather(ul x){if (!x) {return x;}ul f = query(fa, x);return f == x ? x : getfather(f);}void connect(ul x, ul y, ul& fac, ul& rkc, ul& szc){x = getfather(x);y = getfather(y);if (x == y || x == 0 || y == 0) {return;}ul rkx = query(rk, x);ul rky = query(rk, y);if (rkx < rky) {change(fa, x, y, fac);change(sz, y, query(sz, x) + query(sz, y), szc);} else if (rkx > rky) {change(fa, y, x, fac);change(sz, x, query(sz, x) + query(sz, y), szc);} else {change(fa, x, y, fac);change(sz, y, query(sz, x) + query(sz, y), szc);change(rk, y, rky + 1, rkc);}}void search(ul curr){ul fac = 0;ul rkc = 0;ul szc = 0;if (curr == 0) {for (ul i = 1; i <= n; ++i) {push_front(fa[i + n], i);push_front(fa[i], i);push_front(rk[i], 1);push_front(sz[i], 1);}} else {ul i = curr;if (op[i] == 1) {connect(a[i] + n, b[i] + n, fac, rkc, szc);} else if (op[i] == 2) {ul ta = getfather(a[i] + n);if (ta) {change(sz, ta, query(sz, ta) - 1, szc);change(fa, a[i] + n, 0, fac);}} else if (op[i] == 3) {ul ta = getfather(a[i] + n);ul tb = getfather(b[i] + n);if (ta && tb && ta != tb) {change(sz, ta, query(sz, ta) - 1, szc);change(sz, tb, query(sz, tb) + 1, szc);change(fa, a[i] + n, tb, fac);}} else if (op[i] == 4) {ul ta = getfather(a[i] + n);ul tb = getfather(b[i] + n);ans[i] = ta && tb && ta == tb ? 1 : 0;} else if (op[i] == 5) {ul ta = getfather(a[i] + n);if (!ta) {ans[i] = 0;} else {ans[i] = query(sz, ta);}}}for (ul eid = sons[curr]; eid; eid = nodes[eid].next) {ul next = nodes[eid].val;search(next);}if (curr != 0) {while (fac) {pop_front(fa[nodes[fac].val]);pop_front(fac);}while (rkc) {pop_front(rk[nodes[rkc].val]);pop_front(rkc);}while (szc) {pop_front(sz[nodes[szc].val]);pop_front(szc);}}}int main(){std::scanf("%u%u", &n, &m);for (ul i = 1; i <= m; ++i) {std::scanf("%u%u", &op[i], &k[i]);push_front(sons[k[i]], i);if (op[i] == 1 || op[i] == 3 || op[i] == 4) {std::scanf("%u%u", &a[i], &b[i]);} else {std::scanf("%u", &a[i]);}}search(0);for (ul i = 1; i <= m; ++i) {if (op[i] == 4) {std::printf(ans[i] ? "Yes\n" : "No\n");} else if (op[i] == 5) {std::printf("%u\n", ans[i]);}}return 0;}
暴搜就能过。
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul maxn = 18;ul T;ul n;char str[maxn + 1];ul a[maxn];ul g[maxn];std::vector<ul> rg[maxn];ul m[maxn][4];ul rdeg[maxn];const ul inf = 1e9;ul ans;ul ord[maxn];ul reach[1 << maxn];ul ldeg[maxn];void search(ul i, ul remainl, ul cans, ul alr){if ((alr | reach[remainl]) != (1 << n) - 1) {return;}if (ans <= cans) {return;}if (i == n) {ans = cans;return;}ul v = ord[i];for (ul u : rg[v]) {if (!(1 << u & remainl)) {continue;}ul nans = cans - m[u][ldeg[u]];++ldeg[u];nans += m[u][ldeg[u]];search(i + 1, remainl & ~a[u], nans, alr | 1 << v);--ldeg[u];}}int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);for (ul i = 0; i <= n - 1; ++i) {rdeg[i] = 0;ldeg[i] = 0;ord[i] = i;rg[i].resize(0);}for (ul i = 0; i <= n - 1; ++i) {std::scanf("%s", str);g[i] = 0;for (ul j = 0; j <= n - 1; ++j) {g[i] |= ul(str[j] - '0') << j;rdeg[j] += ul(str[j] - '0');if (str[j] - '0') {rg[j].push_back(i);}}}for (ul i = 1; i < (1 << n); ++i) {ul t = 31 - __builtin_clz(i);reach[i] = reach[i & ~(1 << t)] | g[t];}for (ul i = 0; i <= n - 1; ++i) {std::scanf("%s", str);a[i] = 0;for (ul j = 0; j <= n - 1; ++j) {a[i] |= ul(str[j] - '0') << j;}}for (ul i = 0; i <= n - 1; ++i) {std::scanf("%u", &m[i][1]);m[i][2] = m[i][1] * m[i][1];m[i][3] = m[i][2] * m[i][1];}ans = inf;std::sort(ord, ord + n, [&](ul a, ul b){return rdeg[a] < rdeg[b];});search(0, (1 << n) - 1, 0, 0);if (ans != inf) {std::printf("%u\n", ans);} else {std::printf("-1\n");}}return 0;}
简单题
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul T;const ul mod = 1e9 + 7;const ul maxlen = 1e5;char s[maxlen + 2];ul plus(ul a, ul b){return a + b < mod ? a + b : a + b - mod;}ul minus(ul a, ul b){return a < b ? a + mod - b : a - b;}ul mul(ul a, ul b){return ull(a) * ull(b) % mod;}int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {ul tmp = 1;ul sum = 1;std::scanf("%s", s + 1);ul len = std::strlen(s + 1);for (ul i = len; i; --i) {if (s[i] == '1') {sum = plus(sum, tmp);tmp = mul(tmp, 3);} else {tmp = mul(tmp, 2);}}std::printf("%u\n", sum);}return 0;}
用uint64_t f[2]来表示一个从到的映射,当输入为的时候,输出的第位等于f[t >> i & 1] >> i。于是考虑映射和复合的时候应该等于什么。那么有如下结果:
①对于:g[0] = f[0]; g[1] = f[0] & ~a ^ f[1] & a;
②对于:g[1] = f[1]; g[0] = f[0] & ~a ^ f[1] & a;
③对于:b = (f[0] ^ f[1]) & a; g[0] = f[0] ^ b; g[1] = f[1] ^ b;
于是可以完成一个映射和一个半截运算的复合,于是时间复杂度为。
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;using uss = std::uint8_t;const ul maxn = 1e5;ul n;ul q;const ul maxq = 1e5;ull a[maxn + 1];ul totedge;ul totedge0;class edge_t {public:ul next = 0;ul to = 0;};ul s[maxn + 1];edge_t sons[maxn];edge_t sons0[maxn];ul head0[maxn + 1];ul head[maxn + 1];void addedge0(ul a, ul b){++totedge0;sons0[totedge0].to = b;sons0[totedge0].next = head0[a];head0[a] = totedge0;}void addedge(ul a, ul b){++totedge;sons[totedge].to = b;sons[totedge].next = head[a];head[a] = totedge;}const ull full = ~ull(0);ull tmpans[maxn + 1][3][2];ul tim;ul already[maxn + 1];ull ans[maxq + 1][3];class query_t {public:ul d = 0;ul u = 0;ul id = 0;};query_t querys[maxq + 1];ull f(ul s, ull a, ull b){return s == 0 ? (a | b) : (s == 1 ? (a & b) : (a ^ b));}ul d, pos;void search0(ul curr){for (ul eid = head0[curr]; eid; eid = sons0[eid].next) {ul next = sons0[eid].to;addedge(curr, next);search0(next);}}void deal(const ull from[], ul s, ull to[], ull a){if (s == 0) {to[1] = from[1];to[0] = from[0] & ~a ^ from[1] & a;} else if (s == 1) {to[0] = from[0];to[1] = from[0] & ~a ^ from[1] & a;} else {ull b = (from[0] ^ from[1]) & a;to[0] = from[0] ^ b;to[1] = from[1] ^ b;}}ull calc(const ull f[], ull a){return f[0] & ~a ^ f[1] & a;}void search(ul curr){ull cn[2];ull tn[3][2];if (already[curr] == tim) {return;}already[curr] = tim;auto c = tmpans[curr];c[0][0] = 0;c[0][1] = 0;c[1][0] = ~ull(0);c[1][1] = ~ull(0);c[2][0] = 0;c[2][1] = 0;for (ul eid = head[curr]; eid; eid = sons[eid].next) {ul next = sons[eid].to;cn[0] = f(s[next], 0, a[next] + next * d);cn[1] = f(s[next], ~ull(0), a[next] + next * d);c[0][0] |= cn[0];c[0][1] |= cn[1];c[1][0] &= cn[0];c[1][1] &= cn[1];c[2][0] ^= cn[0];c[2][1] ^= cn[1];search(next);auto n = tmpans[next];for (ul i = 0; i <= 2; ++i) {deal(n[i], s[next], tn[i], a[next] + next * d);}c[0][0] |= tn[0][0];c[0][1] |= tn[0][1];c[1][0] &= tn[1][0];c[1][1] &= tn[1][1];c[2][0] ^= tn[2][0];c[2][1] ^= tn[2][1];}}int main(){std::scanf("%u%u", &n, &q);for (ul i = 1; i <= n; ++i) {std::scanf("%llu", &a[i]);}for (ul i = 2; i <= n; ++i) {ul f;std::scanf("%u%u", &f, &s[i]);addedge0(f, i);}search0(1);for (ul i = 1; i <= q; ++i) {std::scanf("%u%u", &querys[i].d, &querys[i].u);querys[i].id = i;}std::sort(querys + 1, querys + q + 1, [](const query_t& a, const query_t& b){return a.d < b.d;});for (ul i = 1, j = 1; i <= q; i = j) {for (j = i; j <= q && querys[j].d == querys[i].d; ++j);d = querys[i].d;++tim;for (ul k = i; k != j; ++k) {ul u = querys[k].u;search(u);ull alpha = a[u] + u * d;auto c = tmpans[u];auto d = ans[querys[k].id];d[0] = calc(c[0], alpha);d[1] = calc(c[1], alpha);d[2] = calc(c[2], alpha);}}for (ul i = 1; i <= q; ++i) {std::printf("%llu %llu %llu\n", ans[i][0], ans[i][1], ans[i][2]);}return 0;}
简单题
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul T;ul n, k, m;const ul maxm = 5e5;const ul maxn = 5e4;class edge_t {public:ul u = 0;ul v = 0;ul w = 0;ul c = 0;};edge_t edges[maxm + 1];ul fa[maxn + 1];ul rk[maxn + 1];ul tot;ul stack[maxm + 1];ul getfather(ul a){return fa[a] == a ? a : fa[a] = getfather(fa[a]);}bool connect(ul a, ul b){a = getfather(a);b = getfather(b);if (a == b) {return false;}if (rk[a] < rk[b]) {fa[a] = b;} else if (rk[a] > rk[b]) {fa[b] = a;} else {fa[a] = b;++rk[b];}return true;}int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u%u", &n, &m, &k);for (ul i = 1; i <= n; ++i) {rk[i] = 0;fa[i] = i;}for (ul i = 1; i <= m; ++i) {std::scanf("%u%u%u%u", &edges[i].u, &edges[i].v, &edges[i].w, &edges[i].c);}std::sort(edges + 1, edges + m + 1, [](const edge_t& a, const edge_t& b){return a.c != b.c ? a.c < b.c : a.w > b.w;});tot = 0;ull sum = 0;for (ul i = 1; i <= m; ++i) {if (edges[i].c) {if (!k) {break;}if (connect(edges[i].u, edges[i].v)) {--n;--k;sum += edges[i].w;} else {++tot;stack[tot] = i;}} else {n -= connect(edges[i].u, edges[i].v);sum += edges[i].w;}}if (n != 1) {std::printf("-1\n");continue;}for (ul i = 1; i <= k && i <= tot; ++i) {sum += edges[stack[i]].w;}std::printf("%llu\n", sum);}return 0;}
考虑整个字符串的后缀树,然后求出后缀树的深搜序,接着,每当砍掉后边一部分,那么一个后缀在后缀树上就会移动到其原始位置的某个祖先那里,所以只需要随着长度减小维护这个即可。注意字符串是随机的,那么公共子串的长度一定不长,这意味着任何节点到根的路径上的节点数不多。再注意到一点,任何两个存在的后缀在长度减小的过程中一定不会处于同一个节点上,请自己证明。
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul q;const ul maxq = 1e6;class query_t {public:ul len = 0;ul k = 0;ul ans = 0;};ul len;ul tot;char str[2];char s[maxq + 1];query_t querys[maxq + 1];class sam_t {public:ul las;class node {public:ul ch[26];ul len = 0;ul fa = 0;node() {std::memset(ch, 0, sizeof(ch));}};std::vector<node> st = std::vector<node>(maxq + maxq);void add(ul c){ul p = las;ul np = las = st.size();st.push_back(node());st[np].len = st[p].len + 1;for ( ; p && !st[p].ch[c]; p = st[p].fa) {st[p].ch[c] = np;}if (!p) {st[np].fa = 1;} else {ul q = st[p].ch[c];if (st[q].len == st[p].len + 1) {st[np].fa = q;} else {ul nq = st.size();st.push_back(node());st[nq] = st[q];st[nq].len = st[p].len + 1;st[q].fa = st[np].fa = nq;for ( ; p && st[p].ch[c] == q; p = st[p].fa) {st[p].ch[c] = nq;}}}}void init() {las = 1;st.resize(0);st.resize(2);}};sam_t sam;class listnode {public:ul next = 0;ul val = 0;};ul listtot;listnode listnodes[maxq + maxq];ul listremain;ul listrestack[maxq + maxq];void push_front(ul& x, ul v){ul tmp;if (listremain) {tmp = listrestack[listremain];--listremain;} else {++listtot;tmp = listtot;}listnodes[tmp].val = v;listnodes[tmp].next = x;x = tmp;}void pop_front(ul& x){++listremain;listrestack[listremain] = x;x = listnodes[x].next;}void moveto(ul& y, ul& x){ul z = listnodes[y].next;listnodes[y].next = x;x = y;y = z;}ul pos[maxq + maxq];void sort(ul len, ul& x, bool dir){if (listnodes[x].next == 0) {return;}ul y = x, b = listnodes[x].next;while (listnodes[b].next) {y = listnodes[y].next;b = listnodes[b].next;b = listnodes[b].next;}ul py = y;y = listnodes[y].next;listnodes[py].next = 0;sort(len, x, !dir);sort(len, y, !dir);ul z = 0;while (x || y) {if (x && y) {if ((s[pos[listnodes[x].val] + len] > s[pos[listnodes[y].val] + len]) == dir) {moveto(x, z);} else {moveto(y, z);}} else if (x) {moveto(x, z);} else {moveto(y, z);}}x = z;}ul sons[maxq + maxq];ul at[maxq + 1];ul dfn[maxq + maxq];ul tim;void search1(ul curr){for (ul eid = sons[curr]; eid; eid = listnodes[eid].next) {ul next = listnodes[eid].val;search1(next);pos[curr] = std::max(pos[curr], pos[next]);}}void search2(ul curr){++tim;dfn[curr] = tim;sort(sam.st[curr].len, sons[curr], 1);while (sons[curr]) {ul next = listnodes[sons[curr]].val;pop_front(sons[curr]);search2(next);}}ul stack[maxq + 1];const ul sz = 1 << 21;ul tree[sz << 1];void change(ul pos, ul x){for (tree[pos |= sz] += x, pos >>= 1; pos; pos >>= 1) {tree[pos] = tree[pos << 1] + tree[pos << 1 | 1];}}ul getsum(ul l, ul r){ul ret = 0;for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {if (~l & 1) {ret += tree[l ^ 1];}if (r & 1) {ret += tree[r ^ 1];}}return ret;}int main(){std::scanf("%u", &q);for (ul i = 1; i <= q; ++i) {ul t;std::scanf("%u", &t);if (t == 1) {std::scanf("%s", str);++len;s[len] = str[0];} else {++tot;std::scanf("%u", &querys[tot].k);querys[tot].len = len;}}sam.init();for (ul i = len; i >= 1; --i) {sam.add(s[i] - 'a');at[i] = sam.las;pos[sam.las] = i;}for (ul i = 2; i != sam.st.size(); ++i) {push_front(sons[sam.st[i].fa], i);}pos[1] = len + 1;search1(1);search2(1);for (ul i = 1; i <= len; ++i) {push_front(stack[i + sam.st[sam.st[at[i]].fa].len - 1], i);change(dfn[at[i]], 1);}ul currlen = len;for (ul i = tot; i; --i) {while (currlen > querys[i].len) {--currlen;while (stack[currlen]) {ul t = listnodes[stack[currlen]].val;pop_front(stack[currlen]);change(dfn[at[t]], -1);at[t] = sam.st[at[t]].fa;if (at[t] != 1) {change(dfn[at[t]], 1);push_front(stack[t + sam.st[sam.st[at[t]].fa].len - 1], t);}}}querys[i].ans = getsum(1, dfn[at[querys[i].k]]);}for (ul i = 1; i <= tot; ++i) {std::printf("%u\n", querys[i].ans);}return 0;}
模数的最大质因子为
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul n, m;const ul maxtot = 2802;ul tot;const ul t = 998857459;ul fac[maxtot + 1];ul val[maxtot + 1];ul pos[maxtot + 1];ul tot2;std::pair<ul, ul> stack[(maxtot * (maxtot + 1) >> 1) + 1];ul tot3;std::pair<ul, ul> stack2[(maxtot * (maxtot + 1) >> 1) + 1];int main(){fac[0] = 1;for (ul i = 1; i <= maxtot; ++i) {fac[i] = ull(fac[i - 1]) * ull(i) % t;}std::scanf("%u%u", &n, &m);for (ul i = 1; i <= n; ++i) {ul a;std::scanf("%u", &a);if (a > maxtot) {continue;}++tot;val[tot] = fac[a];pos[tot] = i;}for (ul i = 1; i <= tot; ++i) {ul sum = 0;for (ul j = i; j <= tot; ++j) {sum = sum + val[j] < t ? sum + val[j] : sum + val[j] - t;++tot2;stack[tot2].first = sum;stack[tot2].second = pos[j] - pos[i] + 1;}}std::sort(stack + 1, stack + tot2 + 1, [](const std::pair<ul, ul>& a, const std::pair<ul, ul>& b){return a.first != b.first ? a.first < b.first : a.second > b.second;});for (ul i = 1; i <= tot2; ++i) {while (tot3 && stack2[tot3].second >= stack[i].second) {--tot3;}++tot3;stack2[tot3] = stack[i];}for (ul i = 1; i <= m; ++i) {ul k;std::scanf("%u", &k);auto it = std::lower_bound(stack2 + 1, stack2 + tot3 + 1, std::pair<ul, ul>(k, 0)) - stack2;if (it == tot3 + 1) {std::printf("-1\n");} else {std::printf("%u\n", stack2[it].second);}}return 0;}
的开头正好是当且仅当:。注意只有当是零的时候才有可能出现“刚好相等”的问题,于是将的情况单独处理,那么该表达式的大于和大于等于可以换一下。故该问题实际就是最小化满足以下条件的:
def getsum(a, b, c, n):if n <= 0 :return 0if a >= c or b >= c :return getsum(a % c, b % c, c, n) + n * (n + 1) // 2 * (a // c) + n * (b // c)if a == 0 :return 0if a * n + b < c :return 0return n * ((a * n + b) // c) - (c - b - 1) // a - getsum(c, c - b - 1, a, (a * n + b) // c - 1)import decimalfrom decimal import Decimaldecimal.getcontext().prec = 1000two = Decimal("2")ten = Decimal("10")instr = input()p = int(instr.split(' ')[0])p0 = Decimal(p);p1 = Decimal(p + 1)k = int(instr.split(' ')[1])for i in range(0, 101) :if p == 2 ** i :k = k - 1alpha = 500a = int(ten.ln() / two.ln() * (10 ** alpha))c = 10 ** alphab1 = int(p1.ln() / two.ln() * (10 ** alpha))b0 = int(p0.ln() / two.ln() * (10 ** alpha))l = -1r = 161173615628205990885158576527746324mid = 0while l + 1 != r :mid = (l + r) // 2if getsum(a, b1, c, mid) - getsum(a, b0, c, mid) >= k :r = midelse :l = midif r == 0 :for i in range(0, 101):if p == 2 ** i :print(i)else :print((r * a + b0) // c + 1)
简单题
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul mod = 998244353;ul plus(ul a, ul b){return a + b < mod ? a + b : a + b - mod;}ul minus(ul a, ul b){return a < b ? a + mod - b : a - b;}ul mul(ul a, ul b){return ull(a) * ull(b) % mod;}void exgcd(li a, li b, li& x, li& y){if (b) {exgcd(b, a % b, y, x);y -= a / b * x;} else {x = 1;y = 0;}}ul inverse(ul a){li x, y;exgcd(a, mod, x, y);return x < 0 ? x + li(mod) : x;}ul n, m;const ul maxn = 1e5;std::vector<bool> ban(256, false);ul trans[64][64];void mul(const ul a[][64], const ul b[][64], ul c[][64]){for (ul i = 0; i != 64; ++i) {for (ul j = 0; j != 64; ++j) {c[i][j] = 0;for (ul k = 0; k != 64; ++k) {c[i][j] = plus(c[i][j], mul(a[i][k], b[k][j]));}}}}void pow(const ul ina[][64], ul b, ul c[][64]){static ul a[64][64];static ul tmp[64][64];std::memcpy(a, ina, sizeof(ul) << 12);for (ul i = 0; i != 64; ++i) {for (ul j = 0; j != 64; ++j) {c[i][j] = i == j;}}while (b) {if (b & 1) {mul(a, c, tmp);std::memcpy(c, tmp, sizeof(ul) << 12);}b >>= 1;mul(a, a, tmp);std::memcpy(a, tmp, sizeof(ul) << 12);}}ul totprime;ul prime[maxn + 1];std::vector<bool> notprime(maxn + 1, false);ul phi[maxn + 1];ul ans = 0;ul curr[64][64];bool able[64][64];int main(){phi[1] = 1;for (ul i = 2; i <= maxn; ++i) {if (!notprime[i]) {++totprime;prime[totprime] = i;phi[i] = i - 1;}for (ul pid = 1; pid <= totprime; ++pid) {ul p = prime[pid];if (i * p > maxn) {break;}notprime[i * p] = true;if (i % p == 0) {phi[i * p] = phi[i] * p;break;} else {phi[i * p] = phi[i] * (p - 1);}}}std::scanf("%u%u", &n, &m);for (ul i = 1; i <= m; ++i) {ul a, b, c, d;std::scanf("%u%u%u%u", &a, &b, &c, &d);ban[a << 0 | b << 2 | c << 4 | d << 6] = true;}for (ul from = 0; from != 64; ++from) {for (ul a : {0, 1, 2, 3}) {if (ban[from << 2 | a]) {continue;}trans[from][(from << 2 | a) & 63] = 1;}}for (ul i = 0; i != 64; ++i) {for (ul j = 0; j != 64; ++j) {able[i][j] = !(ban[(j << 2 | i >> 4) & 255] || ban[(j << 4 | i >> 2) & 255] || ban[(j << 6 | i >> 0) & 255]);}}for (ul d = 1; d <= n; ++d) {if (n % d != 0) {continue;}ul tmp = 0;if (d == 1) {for (ul i = 0; i != 4; ++i) {if (!ban[i << 0 | i << 2 | i << 4 | i << 6]) {tmp = plus(tmp, 1);}}} else if (d == 2) {for (ul i = 0; i != 16; ++i) {if (!ban[i << 0 | i << 4] && !ban[(i >> 2 | i << 2 | i << 6) & 255]) {tmp = plus(tmp, 1);}}} else {pow(trans, d - 3, curr);for (ul i = 0; i != 64; ++i) {for (ul j = 0; j != 64; ++j) {if (able[i][j]) {tmp = plus(tmp, curr[i][j]);}}}}ans = plus(ans, mul(phi[n / d], tmp));}std::printf("%u\n", mul(ans, inverse(n)));return 0;}
启发式合并套树套树。
注意, is up to 是指。
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul maxn = 1e5;ul n, k;ul v[maxn + 1];class listnode {public:ul val = 0;ul next = 0;};ul listtot;listnode listnodes[maxn];void push_front(ul& x, ul v){++listtot;listnodes[listtot].val = v;listnodes[listtot].next = x;x = listtot;}ul sons[maxn + 1];std::mt19937_64 rnd;class node {public:ul key = 0;ul val = 0;ul cnt = 0;ul sum = 0;ul lson = 0;ul rson = 0;ull weight = 0;node() {weight = rnd();}};ul tot = 0;ul remain = 0;ul stack[1 << 22];node tree[1 << 22];void update(ul x){tree[x].sum = tree[x].cnt + tree[tree[x].lson].sum + tree[tree[x].rson].sum;}void lrotate(ul& x){ul y = tree[x].rson;tree[x].rson = tree[y].lson;tree[y].lson = x;update(x);update(y);x = y;}void rrotate(ul& x){ul y = tree[x].lson;tree[x].lson = tree[y].rson;tree[y].rson = x;update(x);update(y);x = y;}ul insert(ul& x, ul key, ul val){if (!x) {if (remain) {x = stack[remain];--remain;} else {++tot;x = tot;}tree[x] = node();tree[x].key = key;tree[x].val = val;tree[x].cnt = 1;update(x);return x;}if (tree[x].key == key) {++tree[x].cnt;update(x);return x;} else if (tree[x].key < key) {ul ret = insert(tree[x].rson, key, val);update(x);if (tree[x].weight < tree[tree[x].rson].weight) {lrotate(x);}return ret;} else if (tree[x].key > key) {ul ret = insert(tree[x].lson, key, val);update(x);if (tree[x].weight < tree[tree[x].lson].weight) {rrotate(x);}return ret;}}ul find(ul x, ul key){if (!x) {return 0;}if (tree[x].key == key) {return x;} else if (tree[x].key < key) {return find(tree[x].rson, key);} else {return find(tree[x].lson, key);}}void kill(ul x){++remain;stack[remain] = x;}ul getsum(ul x, ul t){if (!x) {return 0;}if (tree[x].key > t) {return getsum(tree[x].lson, t);} else if (tree[x].key == t) {return tree[x].sum - tree[tree[x].rson].sum;} else if (tree[x].key < t) {return tree[x].sum - tree[tree[x].rson].sum + getsum(tree[x].rson, t);}}ul tot2;ul stack2[maxn + maxn + 1];ul tot3;ul stack3[maxn + maxn + 1];ull ans = 0;void search(ul curr, ul depth, ul& blob, ul& sz){blob = 0;sz = 0;for (ul eid = sons[curr]; eid; eid = listnodes[eid].next) {ul next = listnodes[eid].val;ul nextblob;ul nextsz;search(next, depth + 1, nextblob, nextsz);if (sz < nextsz) {std::swap(blob, nextblob);}sz += nextsz;++tot2;stack2[tot2] = nextblob;while (tot2) {ul it2 = stack2[tot2];--tot2;if (!it2) {continue;}++tot2;stack2[tot2] = tree[it2].rson;++tot2;stack2[tot2] = tree[it2].lson;auto currit2 = find(blob, v[curr] + v[curr] - tree[it2].key);if (!currit2) {continue;}++tot3;stack3[tot3] = tree[it2].val;while (tot3) {ul it3 = stack3[tot3];--tot3;if (!it3) {continue;}++tot3;stack3[tot3] = tree[it3].rson;++tot3;stack3[tot3] = tree[it3].lson;ull data = getsum(tree[currit2].val, std::max(depth + depth + k, tree[it3].key) - tree[it3].key);ans += 2 * tree[it3].cnt * data;}}++tot2;stack2[tot2] = nextblob;while (tot2) {ul it2 = stack2[tot2];--tot2;if (!it2) {continue;}++tot2;stack2[tot2] = tree[it2].rson;++tot2;stack2[tot2] = tree[it2].lson;auto currit2 = insert(blob, tree[it2].key, 0);++tot3;stack3[tot3] = tree[it2].val;while (tot3) {ul it3 = stack3[tot3];--tot3;if (!it3) {continue;}++tot3;stack3[tot3] = tree[it3].rson;++tot3;stack3[tot3] = tree[it3].lson;for (ul i = 1; i <= tree[it3].cnt; ++i) {insert(tree[currit2].val, tree[it3].key, 0);}kill(it3);}kill(it2);}}++sz;auto currit2 = insert(blob, v[curr], 0);insert(tree[currit2].val, depth, 0);}int main(){rnd.seed(std::time(0));std::scanf("%u%u", &n, &k);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &v[i]);}for (ul i = 2; i <= n; ++i) {ul f;std::scanf("%u", &f);push_front(sons[f], i);}ul blob, sz;search(1, 0, blob, sz);std::printf("%llu\n", ans);return 0;}
简单题
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul maxn = 100;ul n;ul a[maxn + 1][maxn + 1];std::pair<ul, li> score[maxn + 1];int main(){std::scanf("%u", &n);for (ul i = 1; i <= n; ++i) {for (ul j = 1; j <= n; ++j) {std::scanf("%u", &a[i][j]);}}for (ul i = 1; i <= n; ++i) {for (ul j = 1; j <= n; ++j) {if (i == j) {continue;}if (a[i][j] > a[j][i]) {score[i].first += 3;} else if (a[i][j] == a[j][i]) {score[i].first += 1;}score[i].second += a[i][j];score[i].second -= a[j][i];}}ul mxid;ul mxcnt;std::pair<ul, li> mx(0, -1e9);for (ul i = 1; i <= n; ++i) {if (mx < score[i]) {mxid = i;mxcnt = 0;mx = score[i];}if (mx == score[i]) {++mxcnt;}}if (mxcnt == 1) {std::printf("%u\n", mxid);} else {std::printf("play-offs\n");}return 0;}
首先
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul mod = 1e9 + 7;ul plus(ul a, ul b){return a + b < mod ? a + b : a + b - mod;}ul minus(ul a, ul b){return a < b ? a + mod - b : a - b;}ul mul(ul a, ul b){return ull(a) * ull(b) % mod;}void exgcd(li a, li b, li& x, li& y){if (b) {exgcd(b, a % b, y, x);y -= a / b * x;} else {x = 1;y = 0;}}ul inverse(ul a){li x, y;exgcd(a, mod, x, y);return x < 0 ? x + li(mod) : x;}ul pow(ul a, ul b){ul ret = 1;while (b) {if (b & 1) {ret = mul(ret, a);}a = mul(a, a);b >>= 1;}return ret;}ul t;ll x, y;const ul maxt = 1e5;ul f0(ul q){ul fourq = mul(4, q);if (fourq == 1) {return t;}return mul(minus(pow(fourq, t + 1), fourq), inverse(minus(fourq, 1)));}ul f1(ul q){return t;}ul f2(ul q){ul fourqp2 = plus(mul(4, q), 2);if (fourqp2 == 1) {return plus(t, 1);}return plus(mul(minus(pow(fourqp2, t + 1), fourqp2), inverse(minus(fourqp2, 1))), 1);}ul f3(ul q){return mul(minus(plus(mul(2, t), pow(minus(0, 1), t)), 1), inverse(4));}ul fac[maxt + 2];ul fiv[maxt + 2];ul facm[maxt + 2];ul fivm[maxt + 2];ul calc(const ul g[], ul deg, ul x){static ul xmjpre[maxt + 3];static ul xmjsuf[maxt + 3];xmjpre[0] = x;for (ul j = 1; j <= deg; ++j) {xmjpre[j] = mul(xmjpre[j - 1], minus(x, j));}xmjsuf[deg + 1] = 1;for (ul j = deg; ~j; --j) {xmjsuf[j] = mul(xmjsuf[j + 1], minus(x, j));}ul ans = 0;for (ul i = 1; i <= deg; ++i) {ans = plus(ans, mul(g[i], mul(mul(xmjpre[i - 1], xmjsuf[i + 1]), mul(fiv[i], fivm[deg - i]))));}return ans;}ul getans(ll lq, ll rq, ul (*f)(ul), ul deg){static ul g[maxt + 2];g[0] = 0;for (ul i = 1; i <= deg; ++i) {g[i] = plus(g[i - 1], f((lq + i - 1) % mod));}return calc(g, deg, (rq - lq + 1) % mod);}ll ceil(ll a){return a > 0 ? (a + 3) / 4 : a / 4;}ll floor(ll a){return a < 0 ? (a - 3) / 4 : a / 4;}int main(){fac[0] = 1;facm[0] = 1;for (ul i = 1; i <= maxt + 1; ++i) {fac[i] = mul(fac[i - 1], i);facm[i] = mul(facm[i - 1], minus(0, i));}fiv[maxt + 1] = inverse(fac[maxt + 1]);fivm[maxt + 1] = inverse(facm[maxt + 1]);for (ul i = maxt + 1; i; --i) {fiv[i - 1] = mul(fiv[i], i);fivm[i - 1] = mul(fivm[i], minus(0, i));}std::scanf("%u%lld%lld", &t, &x, &y);std::printf("%u\n", plus(plus(getans(ceil(x), floor(y), f0, t + 1), getans(ceil(x - 1), floor(y - 1), f1, 1)), plus(getans(ceil(x - 2), floor(y - 2), f2, t + 1), getans(ceil(x - 3), floor(y - 3), f3, 1))));return 0;}