@qq290637843
2021-01-23T04:40:27.000000Z
字数 25702
阅读 346
题目见https://www.jisuanke.com/contest/5527/challenges,其中N题不知道题面在哪找。
按照是否有第一类加成和是否有第二类加成分为四类,每一类最多留下五个基价值最高的不同名字,然后总共最多二十张卡作为选择,最后暴力二十选五。
#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;using card = std::pair<std::string, std::string>;std::map<card, ul> map1;ul n;char str1[11], str2[11];std::string bonuscolor;using namep = std::pair<std::string, ul>;std::vector<namep> other[2];std::map<std::string, ul> nameid;ul power[16][2];std::set<std::string> already;ul tot = 0;using cd = std::pair<ul, ul>;cd sp[21];int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);map1.clear();for (ul i = 1; i <= n; ++i) {ul p;std::scanf("%s%s%u", &str1, &str2, &p);auto& v = map1[card(std::string(str1), std::string(str2))];v = std::max(v, p);}nameid.clear();for (ul i = 1; i <= 5; ++i) {std::scanf("%s", &str1);nameid[str1] = i;}std::scanf("%s", &str1);bonuscolor = str1;other[0].resize(0);other[1].resize(0);std::memset(power, 0, sizeof(power));for (const auto& p : map1) {auto it = nameid.find(p.first.first);if (it != nameid.end()) {auto& v = power[it->second][p.first.second == bonuscolor];v = std::max(v, p.second);} else {other[p.first.second == bonuscolor].push_back(namep(p.first.first, p.second));}}std::sort(other[0].begin(), other[0].end(), [](const namep& a, const namep& b){return a.second > b.second;});std::sort(other[1].begin(), other[1].end(), [](const namep& a, const namep& b){return a.second > b.second;});for (ul i = 0; i <= 1; ++i) {already.clear();for (const auto& p : other[i]) {if (already.insert(p.first).second) {auto& currnameid = nameid[p.first];if (!currnameid) {currnameid = nameid.size();}power[currnameid][i] = p.second;if (already.size() == 5) {break;}}}}tot = 0;for (ul i = 1; i <= nameid.size(); ++i) {for (ul j = 0; j <= 1; ++j) {if (power[i][j]) {++tot;sp[tot].first = i;sp[tot].second = j;}}}ul base = 0;ul ans = 0;ul bonus = 0;for (ul a = 1; a + 4 <= tot; ++a) {base += power[sp[a].first][sp[a].second];if (sp[a].first <= 5) {bonus += 1;}if (sp[a].second) {bonus += 2;}for (ul b = a + 1; b + 3 <= tot; ++b) {if (sp[a].first == sp[b].first) {continue;}base += power[sp[b].first][sp[b].second];if (sp[b].first <= 5) {bonus += 1;}if (sp[b].second) {bonus += 2;}for (ul c = b + 1; c + 2 <= tot; ++c) {if (sp[c].first == sp[b].first) {continue;}base += power[sp[c].first][sp[c].second];if (sp[c].first <= 5) {bonus += 1;}if (sp[c].second) {bonus += 2;}for (ul d = c + 1; d + 1 <= tot; ++d) {if (sp[d].first == sp[c].first) {continue;}base += power[sp[d].first][sp[d].second];if (sp[d].first <= 5) {bonus += 1;}if (sp[d].second) {bonus += 2;}for (ul e = d + 1; e <= tot; ++e) {if (sp[e].first == sp[d].first) {continue;}base += power[sp[e].first][sp[e].second];if (sp[e].first <= 5) {bonus += 1;}if (sp[e].second) {bonus += 2;}ans = std::max(ans, base * (10 + bonus) / 10);base -= power[sp[e].first][sp[e].second];if (sp[e].first <= 5) {bonus -= 1;}if (sp[e].second) {bonus -= 2;}}base -= power[sp[d].first][sp[d].second];if (sp[d].first <= 5) {bonus -= 1;}if (sp[d].second) {bonus -= 2;}}base -= power[sp[c].first][sp[c].second];if (sp[c].first <= 5) {bonus -= 1;}if (sp[c].second) {bonus -= 2;}}base -= power[sp[b].first][sp[b].second];if (sp[b].first <= 5) {bonus -= 1;}if (sp[b].second) {bonus -= 2;}}base -= power[sp[a].first][sp[a].second];if (sp[a].first <= 5) {bonus -= 1;}if (sp[a].second) {bonus -= 2;}}std::printf("%u\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;ul n;const li maxn = 1000;li v[maxn][maxn];ul a, b;int main(){std::scanf("%u", &n);for (ul i = 0; i < n; ++i) {for (ul j = 0; j < n; ++j) {std::scanf("%d", &v[i][j]);if (v[i][j] < 0) {a = i;b = j;}}}std::printf("%d\n", v[(a + 1) % n][b] + v[a][(b + 1) % n] - v[(a + 1) % n][(b + 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 n, k;const ul maxn = 1e6;using pulul = std::pair<ul, ul>;std::deque<pulul> cqueue;std::deque<pulul> vqueueu;std::deque<pulul> vqueued;ul c[maxn + 1];ul g(ul x, bool re){if (re) {ul l, r;l = -1;r = vqueueu.size() - 1;while (l + 1 != r) {ul mid = l + r >> 1;if (vqueueu[mid].first < x) {l = mid;} else {r = mid;}}ul u = vqueueu[r].second;l = -1;r = vqueued.size() - 1;while (l + 1 != r) {ul mid = l + r >> 1;if (vqueued[mid].first < x) {l = mid;} else {r = mid;}}ul d = vqueued[r].second;return d - u;} else {while (vqueueu.front().first < x) {vqueueu.pop_front();}while (vqueued.front().first < x) {vqueued.pop_front();}return vqueued.front().second - vqueueu.front().second;}}int main(){std::scanf("%u%u", &n, &k);for (ul i = 1; i <= n; ++i) {ul v;std::scanf("%u", &v);v ^= c[i - 1];while (vqueueu.size() && vqueueu.back().second >= v) {vqueueu.pop_back();}vqueueu.push_back(pulul(i, v));while (vqueued.size() && vqueued.back().second <= v) {vqueued.pop_back();}vqueued.push_back(pulul(i, v));if (i < k) {c[i] = 0;} else if (i < k + k) {c[i] = vqueued.front().second - vqueueu.front().second;} else {while (cqueue.size() && cqueue.back().second >= c[i - k]) {cqueue.pop_back();}cqueue.push_back(pulul(i - k, c[i - k]));while (cqueue.size() >= 2 && std::max(cqueue[0].second, g(cqueue[0].first + 1, false)) >= std::max(cqueue[1].second, g(cqueue[1].first + 1, true))) {cqueue.pop_front();}c[i] = std::max(cqueue[0].second, g(cqueue[0].first + 1, false));}}for (ul i = 1; i <= n; ++i) {std::printf("%u\n", c[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 mod = 59964251;const ul phi = 59870352;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;}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;ul m, d, k;char str[100002];ull n;const ul maxm = 1e5;ul sak[maxm + 1];ul ak[maxm + 1];std::vector<ul> prime;ul mu[maxm + 1];bool notprime[maxm + 1];int main(){mu[1] = 1;for (ul i = 2; i <= maxm; ++i) {if (!notprime[i]) {mu[i] = minus(0, 1);prime.push_back(i);}for (ul p : prime) {if (p * i > maxm) {break;}notprime[p * i] = true;if (i % p == 0) {mu[p * i] = 0;break;} else {mu[p * i] = minus(0, mu[i]);}}}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%s", str + 1);n = 0;for (ul i = 1; str[i]; ++i) {n *= 10;n += str[i] - '0';if (n >= phi + phi) {n %= phi;n += phi;}}std::scanf("%u%u%u", &m, &d, &k);for (ul a = 1; a * d <= m; ++a) {ak[a] = pow(a, k);sak[a] = plus(sak[a - 1], ak[a]);}ul ans = 0;for (ul t = 1; t * d <= m; ++t) {if (mu[t]) {ans = plus(ans, mul(pow(mul(ak[t], sak[m / d / t]), n), mu[t]));}}ans = mul(ans, pow(pow(d, k), n));std::printf("%u\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;ul n, k;const ul maxn = 1e5;ul cnt[maxn + 1];ul A[maxn + 1][32][32];ul a;ul f[maxn + 1];std::vector<ul> sons[maxn + 1];std::vector<ul> stack;void search(ul curr){ul depth = stack.size();stack.push_back(curr);if (depth >= k + 1) {cnt[stack[depth - k - 1]] -= cnt[curr];for (ul s = 0; s != 32; ++s) {for (ul t = 0; t != 32; ++t) {A[stack[depth - k - 1]][s][t] -= A[curr][s][t];}}}for (ul next : sons[curr]) {search(next);}stack.pop_back();}int main(){std::scanf("%u%u", &n, &k);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &a);for (ul s = 0; s != 32; ++s) {if (a >> s & 1) {for (ul t = 0; t != 32; ++t) {if (a >> t & 1) {A[i][s][t] = 1;}}}}cnt[i] = 1;}for (ul i = 2; i <= n; ++i) {std::scanf("%u", &f[i]);sons[f[i]].push_back(i);}for (ul i = n; i >= 2; --i) {cnt[f[i]] += cnt[i];for (ul s = 0; s != 32; ++s) {for (ul t = 0; t != 32; ++t) {A[f[i]][s][t] += A[i][s][t];}}}search(1);for (ul i = 1; i <= n; ++i) {ull ans = 0;for (ul s = 0; s != 32; ++s) {for (ul t = 0; t != 32; ++t) {ans += ull(cnt[i]) * ull(A[i][s][t]) + ull(A[i][s][s]) * ull(A[i][t][t]) - 2 * ull(A[i][s][t]) * ull(A[i][t][t]) - 2 * ull(A[i][s][t]) * ull(A[i][s][s]) + 2 * ull(A[i][s][t]) * ull(A[i][s][t]) << s << t;}}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 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;}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;}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 bm(const ul s[], ul cc[], ul nn){static ul bb[200];static ul tt[200];cc[0] = 1;bb[0] = 1;ul tl;ul bl = 0;ul l = 0;ul m = 1;ul b = 1;for (ul n = 0; n != nn; ++n) {ul d = 0;for (ul i = 0; i <= l; ++i) {d = plus(d, mul(cc[i], s[n - i]));}if (d == 0) {++m;} else if (l + l <= n) {std::memcpy(tt, cc, sizeof(ul) * (l + 1));tl = l;std::memset(&cc[l + 1], 0, sizeof(ul) * (n - l - l + 1));l = n + 1 - l;ul lambda = mul(inverse(b), d);for (ul i = 0; i <= bl; ++i) {cc[i + m] = minus(cc[i + m], mul(lambda, bb[i]));}bl = tl;std::memcpy(bb, tt, sizeof(ul) * (bl + 1));b = d;m = 1;} else {ul lambda = mul(inverse(b), d);for (ul i = 0; i <= bl; ++i) {cc[i + m] = minus(cc[i + m], mul(lambda, bb[i]));}++m;}}return l;}ul linearrec(const ul s[], const ul tcc[], ul len, ull n){static ul cc[200];static ul ret[200];static ul temp[200];if (n < len) {return s[n];}std::memcpy(cc, tcc, sizeof(ul) * (len + 1));std::memset(ret, 0, sizeof(ul) * len);ret[0] = 1;ul dret = 0;for (ull t = ull(1) << 63 - __builtin_clzll(n); t; t >>= 1) {std::memset(temp, 0, sizeof(ul) * (dret + dret + 1));for (ul i = 0; i <= dret; ++i) {temp[i + i] = plus(temp[i + i], mul(ret[i], ret[i]));for (ul j = i + 1; j <= dret; ++j) {ul tp = mul(ret[i], ret[j]);temp[i + j] = plus(temp[i + j], plus(tp, tp));}}for (ul i = dret + dret; i >= len; --i) {ul lambda = minus(0, temp[i]);if (!lambda) {continue;}for (ul j = 0; j <= len; ++j) {temp[i - j] = plus(temp[i - j], mul(cc[j], lambda));}}std::memcpy(ret, temp, sizeof(ul) * len);dret = std::min(dret + dret, len - ul(1));if (t & n) {for (ul i = dret + 1; i; --i) {ret[i] = ret[i - 1];}ret[0] = 0;++dret;if (dret == len) {ul lambda = minus(0, ret[len]);if (lambda) {for (ul i = 0; i <= len; ++i) {ret[len - i] = plus(ret[len - i], mul(cc[i], lambda));}}--dret;}}}ul out = 0;for (ul i = 0; i != len; ++i) {out = plus(out, mul(s[i], ret[i]));}return out;}const ul maxt = 40;ul s[maxt + 1][maxt + maxt + 4];ul cc[maxt + 1][maxt + 3];ul len[maxt + 1];ull n;using lf = double;ull powroot(ull a, ul b){ull tmp = std::llround(std::pow(a, lf(1) / lf(b)));if (std::pow(tmp, b) > n) {--tmp;}return tmp;}const ul inv2 = mod + 1 >> 1;int main(){std::scanf("%llu", &n);for (ul t = 2; (ull(1) << t - 1) <= n; ++t) {for (ul x = 1; x <= t + t + 3; ++x) {s[t][x] = plus(s[t][x - 1], pow(x, t));}len[t] = bm(s[t], cc[t], t + t + 4);}ul ans = 0;for (ul k = 1; (ull(1) << k) <= n; ++k) {ull l = powroot(n, k + 1) + 1;ull r = powroot(n, k);ans = plus(ans, mul(k, mul((n + 1) % mod, mul((l + r) % mod, mul((r - l + 1) % mod, inv2)))));ans = minus(ans, minus(linearrec(s[k + 1], cc[k + 1], len[k + 1], r), 1));}std::printf("%u\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;ul n, q;const ul sz = 1 << 17;li tree[11][sz << 1];void change(ul l, ul r, li val, li tree[]){li temp;for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {if (~l & 1) {tree[l ^ 1] += val;}if (r & 1) {tree[r ^ 1] += val;}temp = std::max(tree[l], tree[l ^ 1]);tree[l] -= temp;tree[l ^ 1] -= temp;tree[l >> 1] += temp;temp = std::max(tree[r], tree[r ^ 1]);tree[r] -= temp;tree[r ^ 1] -= temp;tree[r >> 1] += temp;}for (ul i = l; i >> 1; i >>= 1) {temp = std::max(tree[i], tree[i ^ 1]);tree[i] -= temp;tree[i ^ 1] -= temp;tree[i >> 1] += temp;}}li& maxx(li& a, li b){return a = std::max(a, b);}li query(ul l, ul r, const li tree[]){li lans = -1e7;li rans = -1e7;for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {if (~l & 1) {maxx(lans, tree[l ^ 1]);}if (r & 1) {maxx(rans, tree[r ^ 1]);}lans += tree[l >> 1];rans += tree[r >> 1];}li ans = std::max(lans, rans);for (ul i = l; i >> 1; i >>= 1) {ans += tree[i >> 1];}return ans;}char str[20];int main(){std::scanf("%u%u", &n, &q);for (ul i = 1; i <= q; ++i) {std::scanf("%s", str);if (str[1] == 'U') {ul l, r, x;std::scanf("%u%u%u", &l, &r, &x);for (ul p : {2, 3, 5, 7}) {ul t = 0;while (x % p == 0) {x /= p;++t;}change(l, r, t, tree[p]);}} else {ul l, r;std::scanf("%u%u", &l, &r);std::printf("ANSWER %d\n", std::max(std::max(query(l, r, tree[2]), query(l, r, tree[3])), std::max(query(l, r, tree[5]), query(l, r, tree[7]))));}}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, x, y, s;const ul maxn = 25000;ul rk[maxn + 1];ul fa[maxn + 1];ul getfather(ul x){return fa[x] == x ? x : fa[x] = getfather(fa[x]);}void connect(ul a, ul b){a = getfather(a);b = getfather(b);if (a == b) {return;}if (rk[a] > rk[b]) {fa[b] = a;} else if (rk[b] > rk[a]) {fa[a] = b;} else {fa[a] = b;++rk[b];}}class edge_t {public:ul to = 0;li c = 0;edge_t()=default;edge_t(ul a, li b): to(a), c(b) {}};std::vector<edge_t> edges[maxn + 1];std::vector<ul> bigedges[maxn + 1];ul cnt[maxn + 1];std::vector<ul> order;std::deque<ul> queue;bool operator<(const edge_t& a, const edge_t& b){return a.c > b.c;}std::priority_queue<edge_t> heap[maxn + 1];li dis[maxn + 1];const li inf = 250000001;int main(){std::scanf("%u%u%u%u", &n, &x, &y, &s);for (ul i = 1; i <= n; ++i) {dis[i] = inf;fa[i] = i;}for (ul i = 1; i <= x; ++i) {ul a, b, c;std::scanf("%u%u%u", &a, &b, &c);edges[a].push_back(edge_t(b, c));edges[b].push_back(edge_t(a, c));connect(a, b);}for (ul i = 1; i <= y; ++i) {ul a, b;li c;std::scanf("%u%u%d", &a, &b, &c);edges[a].push_back(edge_t(b, c));bigedges[getfather(a)].push_back(getfather(b));++cnt[getfather(b)];}for (ul i = 1; i <= n; ++i) {if (getfather(i) != i) {continue;}if (cnt[i] == 0) {queue.push_back(i);}}while (queue.size()) {ul curr = queue.front();queue.pop_front();order.push_back(curr);for (ul next : bigedges[curr]) {--cnt[next];if (!cnt[next]) {queue.push_back(next);}}}dis[s] = 0;heap[getfather(s)].push(edge_t(s, 0));for (const auto t : order) {while (heap[t].size()) {auto curr = heap[t].top();heap[t].pop();if (dis[curr.to] != curr.c) {continue;}for (const auto& next : edges[curr.to]) {if (dis[next.to] > curr.c + next.c) {dis[next.to] = curr.c + next.c;heap[getfather(next.to)].push(edge_t(next.to, curr.c + next.c));}}}}for (ul i = 1; i <= n; ++i) {if (dis[i] == inf) {std::printf("NO PATH\n");} else {std::printf("%d\n", dis[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;using vul = std::vector<ul>;ul x, y;vul operator*(const vul& a, const vul& b){static vul ret;ret.resize(0);if (a.empty() || b.empty()) {return ret;}ret.resize(a.size() + b.size() - 1, 0);for (ul i = 0; i != a.size(); ++i) {if (a[i]) {for (ul j = 0; j != b.size(); ++j) {ret[i + j] += a[i] * b[j];}}}for (ul i = 0; i != ret.size(); ++i) {ul k = ret[i] / y;ret[i] %= y;if (k) {if (ret.size() == i + 1) {ret.push_back(0);}ret[i + 1] += k;}}return ret;}vul operator+(const vul& a, const vul& b){static vul ret;ret.resize(std::max(a.size(), b.size()));for (ul i = 0; i != ret.size(); ++i) {ret[i] = (i < a.size() ? a[i] : ul(0)) + (i < b.size() ? b[i] : ul(0));}for (ul i = 0; i != ret.size(); ++i) {ul k = ret[i] / y;ret[i] %= y;if (k) {if (ret.size() == i + 1) {ret.push_back(0);}ret[i + 1] += k;}}return ret;}vul xv, currv, pv;ul ctv[256];ul vtc[62];char z[121];int main(){std::scanf("%u%u", &x, &y);while (x) {xv.push_back(x % y);x /= y;}for (ul i = 0; i <= 9; ++i) {ctv['0' + i] = i;vtc[i] = '0' + i;}for (ul i = 0; i <= 25; ++i) {ctv['A' + i] = 10 + i;vtc[10 + i] = 'A' + i;}for (ul i = 0; i <= 25; ++i) {ctv['a' + i] = 36 + i;vtc[36 + i] = 'a' + i;}std::scanf("%s", z);for (ul i = 0; z[i]; ++i) {ul p = ctv[z[i]];pv.resize(0);while (p) {pv.push_back(p % y);p /= y;}currv = currv * xv + pv;}if (currv.empty()) {std::printf("0\n");return 0;}for (ul i = currv.size() - 1; ~i; --i) {std::putchar(char(vtc[currv[i]]));}std::putchar('\n');return 0;}
首先注意到,实际就是要求给每条边赋权,使得所有点的度数都是偶数,或者有两个奇度点,且其中一个是,那么显然所有边最少被走一次,最多被走两次。那么可以考虑动态规划。代码中ans_t的数组v[][],表示根当前度数奇偶性为,根之外有个奇度点的最小花费,而ans2_t中的数组v[][][]是给“有两个根的结构”准备的,其中和分别表示两头的度数的奇偶性,表示两头之外有多少个奇度点。至于深搜过程,实际就是点双连通分量的写法,dfn[]表示的深搜序,low[]表示从出发走一些(可以是零条)树边最多再走一条回边能到达的深搜序最小的点的深搜序。
#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, m;class edge_t {public:ul to = 0;ul len = 0;edge_t()=default;edge_t(ul a, ul b): to(a), len(b) {}};std::vector<edge_t> edges[maxn + 1];ul dfn[maxn + 1];ul low[maxn + 1];const ull inf = 1e18;class ans_t {public:ull v[2][2];ans_t() {for (ul a : {0, 1}) {for (ul b : {0, 1}) {v[a][b] = inf;}}}ans_t(ul x) {for (ul a : {0, 1}) {for (ul b : {0, 1}) {v[a][b] = inf;}}v[0][0] = 0;}ull* operator[](ul x) {return v[x];}const ull* operator[](ul x) const {return v[x];}};class ans2_t {public:ull v[2][2][2];ans2_t() {for (ul a : {0, 1}) {for (ul b : {0, 1}) {for (ul c : {0, 1}) {v[a][b][c] = inf;}}}}using ttt = ull[2];ttt* operator[](ul x) {return v[x];}const ttt* operator[](ul x) const {return v[x];}};ans_t ans[maxn + 1];ans_t deal1(const ans_t& a, const ans_t& b, ul len){ans_t ret;for (ul ar : {0, 1}) {for (ul al : {0, 1}) {if (a[ar][al] == inf) {continue;}for (ul br : {0, 1}) {for (ul bl : {0, 1}) {if (al && bl) {continue;}if (b[br][bl] == inf) {continue;}for (ul w : {1, 2}) {ul cr = (ar ^ w) & 1;ul cl = al + ((br ^ w) & 1) + bl;if (cl >= 2) {continue;}ret[cr][cl] = std::min(ret[cr][cl], a[ar][al] + b[br][bl] + w * len);}}}}}return ret;}ans2_t deal2(const ans_t& a, const ans_t& b, ul len){ans2_t ret;for (ul ar : {0, 1}) {for (ul al : {0, 1}) {if (a[ar][al] == inf) {continue;}for (ul br : {0, 1}) {for (ul bl : {0, 1}) {if (al && bl) {continue;}if (b[br][bl] == inf) {continue;}for (ul w : {1, 2}) {ul cr1 = (ar ^ w) & 1;ul cr2 = (br ^ w) & 1;ul cl = al + bl;ret[cr1][cr2][cl] = std::min(ret[cr1][cr2][cl], a[ar][al] + b[br][bl] + w * len);}}}}}return ret;}ans2_t deal3(const ans_t& a, const ans2_t& b, ul len){ans2_t ret;for (ul ar : {0, 1}) {for (ul al : {0, 1}) {if (a[ar][al] == inf) {continue;}for (ul br1 : {0, 1}) {for (ul br2 : {0, 1}) {for (ul bl : {0, 1}) {if (al && bl) {continue;}if (b[br1][br2][bl] == inf) {continue;}for (ul w : {1, 2}) {ul cr1 = (ar ^ w) & 1;ul cr2 = br2;ul cl = al + bl + ((br1 ^ w) & 1);if (cl >= 2) {continue;}ret[cr1][cr2][cl] = std::min(ret[cr1][cr2][cl], a[ar][al] + b[br1][br2][bl] + w * len);}}}}}}return ret;}ans_t deal4(const ans_t& a, const ans2_t& b, ul len){ans_t ret;for (ul ar : {0, 1}) {for (ul al : {0, 1}) {if (a[ar][al] == inf) {continue;}for (ul br1 : {0, 1}) {for (ul br2 : {0, 1}) {for (ul bl : {0, 1}) {if (al && bl) {continue;}if (b[br1][br2][bl] == inf) {continue;}for (ul w : {1, 2}) {ul cr = (ar ^ w ^ br2) & 1;ul cl = al + bl + ((br1 ^ w) & 1);if (cl >= 2) {continue;}ret[cr][cl] = std::min(ret[cr][cl], a[ar][al] + b[br1][br2][bl] + w * len);}}}}}}return ret;}ul tim;const ans_t zero(0);void search(ul v, ul u){static std::vector<edge_t> stack;++tim;dfn[v] = tim;low[v] = dfn[v];ans[v] = zero;for (const auto& e : edges[v]) {ul w = e.to;if (!dfn[w]) {stack.push_back(e);search(w, v);low[v] = std::min(low[v], low[w]);if (low[w] == dfn[v]) {auto laste = stack.back();stack.pop_back();ans2_t tmp = deal2(ans[stack.back().to], zero, laste.len);while (stack.back().to != w) {laste = stack.back();stack.pop_back();tmp = deal3(ans[stack.back().to], tmp, laste.len);}stack.pop_back();ans[v] = deal4(ans[v], tmp, e.len);} else if (low[w] > dfn[v]) {ans[v] = deal1(ans[v], ans[w], e.len);stack.pop_back();}} else if (dfn[w] < dfn[v] && w != u) {stack.push_back(e);low[v] = std::min(low[v], dfn[w]);}}}int main(){std::scanf("%u%u", &n, &m);for (ul i = 1; i <= m; ++i) {ul u, v, w;std::scanf("%u%u%u", &u, &v, &w);edges[u].push_back(edge_t(v, w));edges[v].push_back(edge_t(u, w));}search(1, 0);std::printf("%llu\n", std::min(ans[1][0][0], ans[1][1][1]));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;using pulul = std::pair<ul, ul>;ul n, m;const ul maxn = 1000;const ul maxm = 1000;ul a[maxn + 1][maxm + 2];ul b[maxn + 1][maxm + 2];pulul pos[maxn * maxm + 1];ul h[maxn + 1][maxm + 1];ul l[maxn + 1][maxm + 1];std::vector<pulul> stack;int main(){std::scanf("%u%u", &n, &m);for (ul i = 1; i <= n; ++i) {for (ul j = 1; j <= m; ++j) {std::scanf("%u", &a[i][j]);pos[a[i][j]] = pulul(i, j);}}ul ans = 0;for (ul i = 1; i <= n; ++i) {stack.resize(0);stack.push_back(pulul(0, 0));for (ul j = 1; j <= m; ++j) {std::scanf("%u", &b[i][j]);if (a[pos[b[i][j]].first - 1][pos[b[i][j]].second] == b[i - 1][j]) {h[i][j] = h[i - 1][j] + 1;} else {h[i][j] = 1;}if (a[pos[b[i][j]].first][pos[b[i][j]].second - 1] != b[i][j - 1]) {stack.resize(0);stack.push_back(pulul(j - 1, 0));}while (stack.back().second >= h[i][j]) {stack.pop_back();}l[i][j] = stack.back().first + 1;stack.push_back(pulul(j, h[i][j]));}stack.resize(0);stack.push_back(pulul(m + 1, 0));for (ul j = m; j >= 1; --j) {if (a[pos[b[i][j]].first][pos[b[i][j]].second + 1] != b[i][j + 1]) {stack.resize(0);stack.push_back(pulul(j + 1, 0));}while (stack.back().second >= h[i][j]) {stack.pop_back();}ul r = stack.back().first - 1;ans = std::max((r - l[i][j] + 1) * h[i][j], ans);stack.push_back(pulul(j, h[i][j]));}}std::printf("%u\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;using pulul = std::pair<ul, ul>;ul T;ul n, m, k;const ul maxn = 7;const ul maxm = 7;const ul maxk = 5;char str[maxn + 1][maxm + 1][maxk + 1];ul tot;const ul maxtot = 18;pulul pos[maxtot + 1];ul s[maxk + 1];ul val[maxtot][maxtot + 1];ul ban[maxtot][maxtot + 1][2];ul ans[1 << maxtot];ul already[1 << maxtot];ul tim = 0;void search(ul curr){if (already[curr] == tim) {return;}already[curr] = tim;ans[curr] = 0;for (ul mi = curr; __builtin_popcount(mi) >= 2; mi &= ~(1 << __builtin_ctz(mi))) {ul i = __builtin_ctz(mi) + 1;for (ul mj = mi & ~(1 << i - 1); mj; mj &= ~(1 << __builtin_ctz(mj))) {ul j = __builtin_ctz(mj) + 1;if ((curr & ban[i][j][0]) && (curr & ban[i][j][1])) {continue;}ul next = curr & ~(1 << i - 1) & ~(1 << j - 1);search(next);ans[curr] = std::max(ans[curr], ans[next] + val[i][j]);}}}int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u%u", &n, &m, &k);tot = 0;for (ul i = 1; i <= n; ++i) {for (ul j = 1; j <= m; ++j) {std::scanf("%s", str[i][j]);if (str[i][j][0] != '-') {++tot;pos[tot] = pulul(i, j);}}}for (ul i = 0; i <= k; ++i) {std::scanf("%u", &s[i]);}for (ul i = 1; i + 1 <= tot; ++i) {for (ul j = i + 1; j <= tot; ++j) {ul cnt = 0;for (ul q = 0; q != k; ++q) {if (str[pos[i].first][pos[i].second][q] == str[pos[j].first][pos[j].second][q]) {++cnt;}}val[i][j] = s[cnt];ban[i][j][0] = ban[i][j][1] = 0;for (ul q = 1; q <= tot; ++q) {if (q == i || q == j) {continue;}if (pos[q].first == pos[i].first && (pos[q].second >= pos[i].second) == (pos[q].second <= pos[j].second)) {ban[i][j][0] |= 1 << q - 1;}if (pos[q].second == pos[j].second && (pos[q].first >= pos[i].first) == (pos[q].first <= pos[j].first)) {ban[i][j][0] |= 1 << q - 1;}if (pos[q].first == pos[j].first && (pos[q].second >= pos[i].second) == (pos[q].second <= pos[j].second)) {ban[i][j][1] |= 1 << q - 1;}if (pos[q].second == pos[i].second && (pos[q].first >= pos[i].first) == (pos[q].first <= pos[j].first)) {ban[i][j][1] |= 1 << q - 1;}}}}++tim;already[0] = tim;ans[0] = 0;search((1 << tot) - 1);std::printf("%u\n", ans[(1 << tot) - 1]);}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;using pulul = std::pair<ul, ul>;const ul mod = 1e9 + 7;const ul maxn = 1e6;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 h[maxn + 1];ul fac[maxn + 1];ul fiv[maxn + 1];ul inv[maxn + 1];ul f[maxn + 1];ul g[maxn + 1];ul low[maxn + 1];std::vector<ul> prime;ul phi[maxn + 1];ul T;std::vector<pulul> stack;ul ans;ul cnt[30];ul n;void search(ul i, ul k){if (i == stack.size()) {if (k != 1) {ans = plus(ans, mul(phi[k], g[n / k]));}return;}for (cnt[i] = 0; cnt[i] <= stack[i].second; ++cnt[i], k *= stack[i].first) {search(i + 1, k);}}int main(){fac[0] = 1;for (ul i = 1; i <= maxn; ++i) {fac[i] = mul(fac[i - 1], i);}fiv[maxn] = inverse(fac[maxn]);for (ul i = maxn; i >= 1; --i) {fiv[i - 1] = mul(fiv[i], i);inv[i] = mul(fiv[i], fac[i - 1]);}h[0] = 1;h[1] = minus(0, 6);h[2] = minus(0, 16);for (ul n = 2; n + 1 <= maxn; ++n) {h[n + 1] = mul(inv[2], mul(inv[n + 1], minus(mul(24 * n - 12, h[n]), mul(8 * n - 16, h[n - 1]))));}f[1] = mul(3, inv[2]);f[2] = minus(0, 1);for (ul n = 0; n + 1 <= maxn; ++n) {f[n + 1] = minus(f[n + 1], mul(h[n], inv[2]));}h[0] = 1;h[1] = 6;h[2] = 52;for (ul n = 2; n + 1 <= maxn; ++n) {h[n + 1] = mul(inv[2], mul(inv[n + 1], minus(mul(24 * n + 12, h[n]), mul(8 * n, h[n - 1]))));}for (ul n = 0; n + 1 <= maxn; ++n) {g[n + 1] = plus(h[n], h[n]);}for (ul i = 2; i <= maxn; ++i) {if (!low[i]) {low[i] = i;prime.push_back(i);phi[i] = i - 1;}for (ul p : prime) {if (i * p > maxn) {break;}low[i * p] = p;if (i % p == 0) {phi[i * p] = phi[i] * p;break;} else {phi[i * p] = phi[i] * (p - 1);}}}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);ans = f[n];stack.resize(0);ul tn = n;while (tn != 1) {if (stack.empty() || stack.back().first != low[tn]) {stack.push_back(pulul(low[tn], 0));}++stack.back().second;tn /= low[tn];}search(0, 1);std::printf("%u\n", mul(ans, inv[n]));}return 0;}