@qq290637843
2021-04-15T11:48:32.000000Z
字数 29287
阅读 425
题目见https://ac.nowcoder.com/acm/contest/3732
简单题
#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;ull ans = 0;int main(){std::scanf("%u%u", &n, &m);for (ul x = 0; x <= n; ++x) {for (ul y = 0; y <= m; ++y) {ans += ull(std::min(x, n - x) * 2 + 1) * ull(std::min(y, m - y) * 2 + 1) - 1 >> 1;}}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 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;}const ul maxsz = 2e5;ul fac[maxsz + 1];ul fiv[maxsz + 1];ul T;li n, m, k;ul binomial(li a, li b){return (b >= 0 && b <= a) ? mul(fac[a], mul(fiv[a - b], fiv[b])) : ul(0);}int main(){fac[0] = 1;for (ul i = 1; i <= maxsz; ++i) {fac[i] = mul(fac[i - 1], i);}fiv[maxsz] = inverse(fac[maxsz]);for (ul i = maxsz; i >= 1; --i) {fiv[i - 1] = mul(fiv[i], i);}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%d%d%d", &n, &m, &k);k += k;li ans;if (n <= m) {if (n & 1) {--k;}li p = (n + m) / 2;li q = (n + m + 1) / 2;if ((n ^ k) & 1) {ans = 0;} else {ans = mul(binomial(p, (n + k) / 2), binomial(q, (n - k) / 2));}} else {if (m & 1) {if (n & 1) {--k;} else {++k;}}li p = (n + m + 1) / 2;li q = (n + m) / 2;if ((m ^ k) & 1) {ans = 0;} else {ans = mul(binomial(p, (m + k) / 2), binomial(q, (m - k) / 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;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;}const ul maxn = 1e5;ul g[maxn + 1];ul f[maxn + 1];class node {public:ul next = 0;ul val = 0;};ul n, k;ul tot = 0;node nodes[1066751];ul head[maxn + 1];ul ln[maxn + 1];std::vector<bool> notprime(maxn + 1, false);std::vector<ul> primes;int main(){std::scanf("%u%u", &n, &k);for (ul i = 2; i <= n; ++i) {if (!notprime[i]) {primes.push_back(i);ln[i] = 1;}for (ul p : primes) {if (i * p > n) {break;}notprime[i * p] = true;ln[i * p] = ln[i] + 1;if (i % p == 0) {break;}}}for (ul i = 1; i <= n; ++i) {for (ul j = i + i; j <= n; j += i) {++tot;nodes[tot].val = i;nodes[tot].next = head[j];head[j] = tot;}}ul kinv = inverse(k);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &g[i]);}f[1] = 1;for (ul x = 2; x <= n; ++x) {for (ul it = head[x]; it; it = nodes[it].next) {ul d = nodes[it].val;f[x] = plus(f[x], minus(mul(f[d], mul(g[x / d], ln[x / d])), mul(k, mul(mul(f[d], ln[d]), g[x / d]))));}f[x] = mul(mul(f[x], kinv), inverse(ln[x]));}for (ul i = 1; i <= n; ++i) {if (i != 1) {std::putchar(' ');}std::printf("%u", f[i]);}std::putchar('\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;using llf = long double;const ul maxn = 1e5;std::vector<ul> edges[maxn + 1];ll k;ll a[maxn + 1];ul n;ll f[maxn + 1];ll g[maxn + 1];ll sz[maxn + 1];ll sum[maxn + 1];ll premin[maxn + 1];ll sufmin[maxn + 1];void search(ul curr, ul prev){sz[curr] = 1;if (edges[curr].size() == 1) {f[curr] = std::min(a[curr], a[curr] + k - 2);g[curr] = a[curr];return;}for (ul next : edges[curr]) {if (next == prev) {continue;}search(next, curr);sz[curr] += sz[next];}std::sort(edges[curr].begin(), edges[curr].end(), [&](ul a, ul b){return (a == prev) != (b == prev) ? a == prev : f[a] + sz[a] + sz[a] - 1 < f[b] + sz[b] + sz[b] - 1;});sum[0] = 0;premin[0] = 1e18;for (ul i = 1; i != edges[curr].size(); ++i) {ul t = edges[curr][i];sum[i] = sum[i - 1] + sz[t] + sz[t];premin[i] = std::min(premin[i - 1], f[t] - sum[i - 1]);}sufmin[edges[curr].size()] = 1e18;for (ul i = edges[curr].size() - 1; i; --i) {ul t = edges[curr][i];sufmin[i] = std::min(sufmin[i + 1], f[t] - sum[i - 1]);}f[curr] = std::min(std::min(a[curr], premin[edges[curr].size() - 1] - 1), a[curr] + k - sum[edges[curr].size() - 1] - 2);g[curr] = -1e18;for (ul b = 1; b != edges[curr].size(); ++b) {ul t = edges[curr][b];ll tmp = std::min(std::min(std::min(std::min(a[curr], premin[b - 1] - 1), sufmin[b + 1] - 1 + sz[t] + sz[t]), g[t] - 1 - sum[edges[curr].size() - 1] + sz[t] + sz[t]), a[curr] + k - sum[edges[curr].size() - 1] + sz[t] + sz[t] - 2);g[curr] = std::max(g[curr], tmp);}}int main(){std::scanf("%u%lld", &n, &k);for (ul i = 1; i <= n - 1; ++i) {ul x, y;std::scanf("%u%u", &x, &y);edges[x].push_back(y);edges[y].push_back(x);}edges[1].push_back(0);for (ul i = 1; i <= n; ++i) {std::scanf("%lld", &a[i]);}search(1, 0);std::printf("%lld\n", g[1] < 0 ? ll(-1) : g[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;const ul maxn = 1e5;class edge_t {public:ul to;ul val;edge_t()=default;edge_t(ul a, ul b): to(a), val(b) {}};std::vector<edge_t> edges[maxn + 1];ull sum = 0;std::vector<ul> tmp;ull s[maxn + 1];ul n, m;int main(){std::scanf("%u%u", &n, &m);for (ul i = 1; i <= m; ++i) {ul x, y, z;std::scanf("%u%u%u", &x, &y, &z);edges[x].push_back(edge_t(y, z));edges[y].push_back(edge_t(x, z));sum += z;}sum /= m / edges[1].size();for (auto e : edges[1]) {tmp.resize(0);for (ul prev = 1, curr = e.to; ; e = edges[e.to][0].to == prev ? edges[e.to][1] : edges[e.to][0], prev = curr, curr = e.to) {tmp.push_back(e.val);if (e.to == n) {break;}}std::sort(tmp.begin(), tmp.end());for (ul i = 0; i != tmp.size(); ++i) {s[i] += tmp[i] - (i ? tmp[i - 1] : ul(0));}}ull ans = 0;for (ul i = 0; i != tmp.size(); ++i) {ull able = std::min(sum, s[i]);sum -= able;ans += able * i;}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;li check(ul a, ul b){if (a == b || a == 30 || b == 30) {return 0;} else if (a == 31 && b == 32) {return -1;} else if (a == 32 && b == 31) {return 1;} else if (a == 31) {return 1;} else if (b == 31) {return -1;} else if (a > b) {return 1;} else {return -1;}}li check(ul a[], ul b[]){for (ul ai = 1, bi = 1; ; ) {if (ai == 25 || bi == 25) {return bi - ai;}li tmp = check(a[ai], b[bi]);if (tmp >= 0) {++bi;}if (tmp <= 0) {++ai;}}return 0;}ul check2(ul a[], ul b[]){ul ret = 0;if (check(a, b) >= 0) {++ret;}for (ul i = 1; i + 1 <= 24; ++i) {for (ul j = i + 1; j <= 24; ++j) {if (b[i] == b[j]) {continue;}std::swap(b[i], b[j]);if (check(a, b) >= 0) {++ret;}std::swap(b[i], b[j]);}}return ret;}ul T;ul a[25] = {0, 40, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 34, 33, 33, 33, 32, 32, 32, 31, 31, 31, 30, 30};ul b[25] = {0, 40, 39, 38, 38, 37, 37, 36, 36, 35, 35, 34, 34, 34, 33, 33, 33, 32, 32, 32, 31, 31, 31, 30, 30};std::mt19937_64 rnd;void sf(ul a[]){for (ul i = 24; i >= 1; --i) {std::swap(a[i], a[rnd() % i + 1]);}}std::pair<ul, ul> sp[500];ul tot;int main(){for (ul i = 1; i + 1 <= 24; ++i) {for (ul j = i + 1; j <= 24; ++j) {++tot;sp[tot].first = i;sp[tot].second = j;}}rnd.seed(std::time(0));std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {for (ul i = 1; i <= 24; ++i) {std::scanf("%u", &a[i]);}ul cnt = 0;while (true) {ul tmp = check2(a, b);while (tmp) {bool flag = false;for (ul i = tot; i >= 1; --i) {std::swap(sp[rnd() % i + 1], sp[i]);ul s = sp[i].first;ul t = sp[i].second;if (b[s] == b[t]) {continue;}std::swap(b[s], b[t]);ul tmp2 = check2(a, b);if (tmp2 < tmp) {tmp = tmp2;flag = true;break;}std::swap(b[s], b[t]);}if (!flag) {break;}}if (tmp == 0) {for (ul i = 1; i <= 24; ++i) {if (i != 1) {std::putchar(' ');}std::printf("%u", b[i]);}std::putchar('\n');break;}sf(b);}}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 ul maxn = 300;class problem {public:ul time = 0;ul pen = 0;};class person {public:problem p[11];ul cnt = 0;ul sum = 0;ul id = 0;};person guy[maxn + 1];std::string instr;std::stringstream ss;std::stringstream ss2;bool operator<(const person& a, const person& b){if (a.cnt != b.cnt) {return a.cnt > b.cnt;}if (a.sum != b.sum) {return a.sum < b.sum;}for (ul i = 10 - a.cnt + 1; i <= 10; ++i) {if (a.p[i].time != b.p[i].time) {return a.p[i].time < b.p[i].time;}}return a.id > b.id;}person pang;ul set;ul mn[11];ul mnmn = 301;ul stack[11];int main(){std::getline(std::cin, instr);ss.clear();ss.str(instr);for (ul i = 1; i <= 10; ++i) {mn[i] = 301;}ss >> n;ul mx = 0;for (ul i = 1; i <= n - 1; ++i) {std::getline(std::cin, instr);ss.clear();ss.str(instr);guy[i].id = i;for (ul j = 1; j <= 10; ++j) {std::getline(ss, instr, ',');if (instr == "-") {guy[i].p[j].time = 301;guy[i].p[j].pen = 11;} else {ss2.clear();ss2.str(instr);ss2 >> guy[i].p[j].time >> guy[i].p[j].pen;++guy[i].cnt;guy[i].sum += guy[i].p[j].time + guy[i].p[j].pen * 20;mx = std::max(mx, guy[i].p[j].time);mn[j] = std::min(mn[j], guy[i].p[j].time);mnmn = std::min(mnmn, mn[j]);}}std::sort(guy[i].p + 1, guy[i].p + 11, [](const problem& a, const problem& b){return a.time > b.time;});}std::sort(guy + 1, guy + n);std::getline(std::cin, instr);ss.clear();ss.str(instr);guy[n].id = n;for (ul j = 1; j <= 10; ++j) {std::getline(ss, instr, ',');if (instr == "-") {pang.p[j].time = 301;pang.p[j].pen = 11;} else {ss2.clear();ss2.str(instr);ss2 >> pang.p[j].time >> pang.p[j].pen;set |= 1 << j;}}ul ans = 0;for (ul mask = set; ; mask = mask - 1 & set) {ul tot = 0;ul sum = 0;for (ul i = 1; i <= 10; ++i) {if (mask >> i & 1) {++tot;stack[tot] = i;sum += pang.p[i].time;}}if (sum > 300) {continue;}do {guy[n].cnt = tot;guy[n].sum = 0;for (ul i = 1; i <= 10; ++i) {guy[n].p[i].time = 301;guy[n].p[i].pen = 11;}ul currans = 0;ul cmx = 0;ul cmn = 301;for (ul i = 1; i <= tot; ++i) {guy[n].p[stack[i]].time = guy[n].p[stack[i - 1]].time + pang.p[stack[i]].time;guy[n].p[stack[i]].pen = pang.p[stack[i]].pen;guy[n].sum += guy[n].p[stack[i]].time + guy[n].p[stack[i]].pen * 20;cmx = std::max(guy[n].p[stack[i]].time, cmx);cmn = std::min(guy[n].p[stack[i]].time, cmn);if (guy[n].p[stack[i]].time <= mn[stack[i]]) {currans += 800;}}if (mask) {if (cmx >= mx) {currans += 500;}if (cmn <= mnmn) {currans += 700;}}std::sort(guy[n].p + 1, guy[n].p + 11, [](const problem& a, const problem& b){return a.time > b.time;});ul r = std::upper_bound(guy + 1, guy + n, guy[n]) - guy;currans += 5000 / r;if (r <= n / 10) {currans += 1200;} else if (r <= n / 10 * 3) {currans += 800;} else if (r <= n / 10 * 6) {currans += 400;}ans = std::max(ans, currans);} while (std::next_permutation(stack + 1, stack + tot + 1));if (!mask) {break;}}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 ul maxn = 2e5;ul p;ul b[maxn + 1];ul binv[maxn + 1];ul bpre[maxn + 1];ul bpreinv[maxn + 1];ul T;ul mul(ul a, ul b){return ull(a) * ull(b) % p;}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, p, x, y);return x < 0 ? x + li(p) : x;}std::mt19937_64 rnd;class hashmap {public:class node {public:ul key = 0;ul val = 0;};bool ex[1 << 20];node v[1 << 20];ul sz;ul a;ul b;const ul mod = 1e9 + 7;void init(ul n){a = rnd() % (mod - 1) + 1;b = rnd() % mod;sz = 1;while (sz + sz < n + n + n) {sz <<= 1;}std::memset(ex, false, sz * sizeof(bool));}ul& operator[](ul x){ul h = (ull(x) * ull(a) + b) % mod & sz - 1;while (true) {if (!ex[h]) {ex[h] = true;v[h].key = x;v[h].val = 0;return v[h].val;}if (v[h].key == x) {return v[h].val;}h = h + 1 & sz - 1;}}};hashmap cnt;hashmap len;ul calc(ul q){len.init(n + n);ul ret = 0;for (ul i = n; i >= 1; --i) {ul& l = len[b[i]];l = std::max(l, len[mul(b[i], q)] + 1);ret = std::max(ret, l);}return ret;}int main(){rnd.seed(std::time(0));std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u", &n, &p);bpre[0] = 1;for (ul i = 1; i <= n; ++i) {std::scanf("%u", &b[i]);bpre[i] = mul(bpre[i - 1], b[i]);}bpreinv[n] = inverse(bpre[n]);for (ul i = n; i >= 1; --i) {bpreinv[i - 1] = mul(bpreinv[i], b[i]);binv[i] = mul(bpreinv[i], bpre[i - 1]);}ul ans = 0;if (n <= 4) {for (ul i = 1; i + 1 <= n; ++i) {for (ul j = i + 1; j <= n; ++j) {ul q = mul(b[j], binv[i]);ans = std::max(ans, calc(q));}}} else {cnt.init(n + n - 3);for (ul i = 1; i + 1 <= n; ++i) {for (ul j = i + 1; j <= n && j <= i + 2; ++j) {cnt[mul(b[j], binv[i])] += 3 ^ j - i;}}for (ul i = 0; i != cnt.sz; ++i) {if (!cnt.ex[i] || cnt.v[i].val < (n + 1) / 2 * 3 - n - 2) {continue;}ans = std::max(ans, calc(cnt.v[i].key));}}if (ans * 2 >= n) {std::printf("%u\n", ans);} else {std::printf("-1\n");}}return 0;}
牛客这道题没放spj,肏你妈。
#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 lll = __int128;using llf = long double;using lf = double;li sgn(lll x){return x < 0 ? -1 : (x > 0 ? 1 : 0);}const lll bound = 1e18;bool less(lll a, lll b, lll c, lll d){if (sgn(a) != sgn(c)) {return sgn(a) < sgn(c);}if (a < 0) {return less(-c, d, -a, b);}lll q1 = a / b;lll r1 = a - b * q1;lll q2 = c / d;lll r2 = c - d * q2;if (q1 != q2) {return q1 < q2;}if (r1 == 0 || r2 == 0) {return r1 < r2;}if (b <= bound && d <= bound) {return r1 * d < r2 * b;}return less(d, r2, b, r1);}ul n;const ul maxn = 1e5;lll in(){ll tmp;std::scanf("%lld", &tmp);return tmp;}class vec {public:lll x = 0;lll y = 0;lll z = 0;vec()=default;vec(lll a, lll b, lll c): x(a), y(b), z(c) {}};class vecd {public:llf x = 0;llf y = 0;llf z = 0;vecd()=default;vecd(llf a, llf b, llf c): x(a), y(b), z(c) {}vecd(const vec& a): x(a.x), y(a.y), z(a.z) {}};std::ostream& operator<<(std::ostream& os, const vecd& a){return os << '{' << a.x << ',' << a.y << ',' << a.z << '}';}vec p[maxn + 1];vec p2[maxn + 1];std::vector<ul> stack1;std::vector<ul> stack2;std::vector<ul> stackpbuttom;std::vector<ul> stackptop;std::vector<ul> stacknbuttom;std::vector<ul> stackntop;std::vector<ul> stacktop;std::vector<ul> stackbuttom;lll gcd(lll a, lll b){a = a < 0 ? -a : a;b = b < 0 ? -b : b;while (b) {b ^= a ^= b ^= a %= b;}return a;}vec operator^(const vec& a, const vec& b){vec ret = vec(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);lll g = gcd(gcd(ret.x, ret.y), ret.z);if (g) {ret.x /= g;ret.y /= g;ret.z /= g;}return ret;}vec operator-(const vec& a){return vec(-a.x, -a.y, -a.z);}vecd operator-(const vecd& a, const vecd& b){return vecd(a.x - b.x, a.y - b.y, a.z - b.z);}vecd operator^(const vecd& a, const vecd& b){return vecd(a.y * b.z - a.z * b.y, a.z * b.x - a.x * b.z, a.x * b.y - a.y * b.x);}lll operator*(const vec& a, const vec& b){return a.x * b.x + a.y * b.y + a.z * b.z;}llf operator*(const vecd& a, const vecd& b){return a.x * b.x + a.y * b.y + a.z * b.z;}vecd operator*(llf a, const vecd& b){return vecd(a * b.x, a * b.y, a * b.z);}vecd operator*(const vecd& a, llf b){return vecd(a.x * b, a.y * b, a.z * b);}vecd operator/(const vecd& a, llf b){return vecd(a.x / b, a.y / b, a.z / b);}llf norm(const vecd& a){return std::sqrt(a * a);}vecd normalize(const vecd& a){llf len = std::max(std::max(a.x < 0 ? -a.x : a.x, a.y < 0 ? -a.y : a.y), a.z < 0 ? -a.z : a.z);if (!len) {return a;}vecd b = a / len;auto n = norm(b);return b / n;}lll det(const vec& a, const vec& b, const vec& c){return a.x * b.y * c.z + a.y * b.z * c.x + a.z * b.x * c.y - a.z * b.y * c.x - a.y * b.x * c.z - a.x * b.z * c.y;}void gethull(std::vector<ul>& stack1, std::vector<ul>& stack2, std::vector<ul>& stack3){std::sort(stack1.begin(), stack1.end(), [&](ul i, ul j){const vec& a = p[i];const vec& b = p[j];if ((a.z == 0) != (b.z == 0)) {return a.z == 0;}if (a.z && b.z) {return a.x * b.z != b.x * a.z ? a.x * b.z < b.x * a.z : a.y * b.z > b.y * a.z;}if ((a.x == 0) != (b.x == 0)) {return a.x == 0;}if (a.x && b.x) {return a.y * b.x < b.y * a.x;}return false;});stack2.resize(0);for (auto i : stack1) {while (stack2.size() >= 2) {const vec& a = p[stack2[stack2.size() - 2]];const vec& b = p[stack2[stack2.size() - 1]];const vec& c = p[i];bool flag = det(a, b, c) <= 0;if (flag) {stack2.pop_back();} else {break;}}stack2.push_back(i);}std::reverse(stack1.begin(), stack1.end());stack3.resize(0);for (auto i : stack1) {while (stack3.size() >= 2) {const vec& a = p[stack3[stack3.size() - 2]];const vec& b = p[stack3[stack3.size() - 1]];const vec& c = p[i];bool flag = det(a, b, c) <= 0;if (flag) {stack3.pop_back();} else {break;}}stack3.push_back(i);}}void gethulld(std::vector<ul>& stack1, std::vector<ul>& stack2, std::vector<ul>& stack3){std::sort(stack1.begin(), stack1.end(), [&](ul i, ul j){const vec& a = p2[i];const vec& b = p2[j];if ((a.z == 0) != (b.z == 0)) {return a.z == 0;}if (a.z && b.z) {bool flag1 = less(b.x, b.z, a.x, a.z);bool flag2 = less(a.x, a.z, b.x, b.z);return (flag1 || flag2) ? flag2 : less(a.y, a.z, b.y, b.z);}if ((a.x == 0) != (b.x == 0)) {return a.x == 0;}if (a.x && b.x) {return less(-a.y, -a.x, -b.y, -b.x);}return false;});stack2.resize(0);for (auto i : stack1) {while (stack2.size() >= 2) {const vec& a = p[stack2[stack2.size() - 2]];const vec& b = p[stack2[stack2.size() - 1]];const vec& c = p[i];bool flag = det(a, b, c) <= 0;if (flag) {stack2.pop_back();} else {break;}}stack2.push_back(i);}std::reverse(stack1.begin(), stack1.end());stack3.resize(0);for (auto i : stack1) {while (stack3.size() >= 2) {const vec& a = p[stack3[stack3.size() - 2]];const vec& b = p[stack3[stack3.size() - 1]];const vec& c = p[i];bool flag = det(a, b, c) <= 0;if (flag) {stack3.pop_back();} else {break;}}stack3.push_back(i);}}bool out(const vec& a, const vec& b, const vec& c){return det(a, b, c) <= 0;}llf myacos(llf a){return std::acos(std::max(std::min(a, llf(1)), llf(-1)));}llf cnt(const vec& a, const vec& b, const vec& c){return myacos((normalize(normalize(a) ^ normalize(b)) * normalize(normalize(b) ^ normalize(c))));}bool operator==(const vec& a, const vec& b){return a.x == b.x && a.y == b.y && a.z == b.z;}const llf pi = std::acos(llf(-1));const llf hpi = pi * llf(0.5);std::priority_queue<llf, std::vector<llf>, std::greater<llf>> heap;int main(){std::scanf("%u", &n);if (n <= 2) {std::printf("1.0\n");return 0;}for (ul i = 1; i <= n; ++i) {p[i].x = in();p[i].y = in();p[i].z = in();lll g = gcd(gcd(p[i].x, p[i].y), p[i].z);p[i].x /= g;p[i].y /= g;p[i].z /= g;}stack1.resize(0);for (ul i = 1; i <= n; ++i) {if (p[i].z > 0 || p[i].z == 0 && p[i].x < 0 || p[i].z == 0 && p[i].x == 0 && p[i].y > 0) {stack1.push_back(i);}}gethull(stack1, stackpbuttom, stackptop);stack1.resize(0);for (ul i = 1; i <= n; ++i) {if (p[i].z < 0 || p[i].z == 0 && p[i].x > 0 || p[i].z == 0 && p[i].x == 0 && p[i].y < 0) {stack1.push_back(i);p[i].x = -p[i].x;p[i].y = -p[i].y;p[i].z = -p[i].z;}}gethull(stack1, stacknbuttom, stackntop);ul s = 0;ul t = 0;vec zdi;vec xdi;vec ydi;vecd zdir;vecd xdir;vecd ydir;if (!stackpbuttom.size() || !stacknbuttom.size()) {zdir = zdi = vec(0, 0, 1);ydir = ydi = vec(0, 1, 0);xdir = xdi = vec(1, 0, 0);} else {ul s = 0;ul t = 0;for (ul i = 0; i + 1 < stackpbuttom.size() && !s && !t; ++i) {const vec& a = p[stackpbuttom[i]];const vec& b = p[stackpbuttom[i + 1]];ul l = 0, r = stackntop.size();while (l + 1 != r) {ul mid = l + r >> 1;const vec& c = p[stackntop[mid - 1]];const vec& d = p[stackntop[mid]];bool flag = (a ^ b) * (normalize(d) - normalize(c)) >= 0;if (flag) {l = mid;} else {r = mid;}}const vec& c = p[stackntop[l]];if (out(a, b, c)) {s = stackpbuttom[i];t = stackpbuttom[i + 1];}}for (ul i = 0; i + 1 < stacknbuttom.size() && !s && !t; ++i) {const vec& a = p[stacknbuttom[i]];const vec& b = p[stacknbuttom[i + 1]];ul l = 0, r = stackptop.size();while (l + 1 != r) {ul mid = l + r >> 1;const vec& c = p[stackptop[mid - 1]];const vec& d = p[stackptop[mid]];bool flag = (a ^ b) * (normalize(d) - normalize(c)) >= 0;if (flag) {l = mid;} else {r = mid;}}const vec& c = p[stackptop[l]];if (out(a, b, c)) {t = stacknbuttom[i];s = stacknbuttom[i + 1];}}for (ul i = 0; i + 1 < stackptop.size() && !s && !t; ++i) {const vec& a = p[stackptop[i]];const vec& b = p[stackptop[i + 1]];ul l = 0, r = stacknbuttom.size();while (l + 1 != r) {ul mid = l + r >> 1;const vec& c = p[stacknbuttom[mid - 1]];const vec& d = p[stacknbuttom[mid]];bool flag = (a ^ b) * (normalize(d) - normalize(c)) >= 0;if (flag) {l = mid;} else {r = mid;}}const vec& c = p[stacknbuttom[l]];if (out(a, b, c)) {s = stackptop[i];t = stackptop[i + 1];}}for (ul i = 0; i + 1 < stackntop.size() && !s && !t; ++i) {const vec& a = p[stackntop[i]];const vec& b = p[stackntop[i + 1]];ul l = 0, r = stackpbuttom.size();while (l + 1 != r) {ul mid = l + r >> 1;const vec& c = p[stackpbuttom[mid - 1]];const vec& d = p[stackpbuttom[mid]];bool flag = (a ^ b) * (normalize(d) - normalize(c)) >= 0;if (flag) {l = mid;} else {r = mid;}}const vec& c = p[stackpbuttom[l]];if (out(a, b, c)) {t = stackntop[i];s = stackntop[i + 1];}}if (!s && !t) {std::printf("0.0\n");return 0;}for (ul i : stack1) {p[i].x = -p[i].x;p[i].y = -p[i].y;p[i].z = -p[i].z;}zdi = p[s] ^ p[t];ydi = p[s];xdi = ydi ^ zdi;stack1.resize(0);stack2.resize(0);for (ul i = 1; i <= n; ++i) {if (p[i] * zdi == 0) {if (p[i] * xdi < 0 || p[i] * xdi == 0 && p[i] * ydi > 0) {stack1.push_back(i);} else {stack2.push_back(i);}}}std::sort(stack1.begin(), stack1.end(), [&](ul i, ul j){const vec& a = p[i];const vec& b = p[j];lll ax = a * xdi;lll bx = b * xdi;lll ay = a * ydi;lll by = b * ydi;if ((ax == 0) != (bx == 0)) {return ax == 0;}if (ax && bx) {return less(-ay, -ax, -by, -bx);}return false;});std::sort(stack2.begin(), stack2.end(), [&](ul i, ul j){const vec& a = p[i];const vec& b = p[j];lll ax = a * xdi;lll bx = b * xdi;lll ay = a * ydi;lll by = b * ydi;if ((ax == 0) != (bx == 0)) {return ax == 0;}if (ax && bx) {return less(ay, ax, by, bx);}return false;});if (stack2.empty()) {xdir = normalize(xdi);ydir = normalize(ydi);zdir = normalize(zdi);} else {const vec& a = p[stack1.back()];const vec& b = p[stack2.front()];lll ax = a * xdi;lll bx = b * xdi;lll ay = a * ydi;lll by = b * ydi;if (ax == 0 && bx != 0 || ax != 0 && bx != 0 && less(-ay, -ax, by, bx)) {zdi = b ^ a;ydi = b;xdi = ydi ^ zdi;xdir = normalize(xdi);ydir = normalize(ydi);zdir = normalize(zdi);} else if (p[stack2.back()] * xdi != 0 && ax != 0 && (bx == 0 || less(by, bx, -ay, -ax))) {for (ul i = 1; i <= n; ++i) {if (p[i] * zdi > 0) {std::printf("0.5\n");return 0;}}std::printf("1.0\n");return 0;} else {xdi = -zdi;zdi = b;ydi = zdi ^ xdi;xdir = normalize(xdi);ydir = normalize(ydi);zdir = normalize(zdi);stack1.resize(0);for (ul i = 1; i <= n; ++i) {if (p[i] * xdi != 0 || p[i] * ydi != 0) {stack1.push_back(i);}}std::sort(stack1.begin(), stack1.end(), [&](ul i, ul j){const vec& a = p[i];const vec& b = p[j];lll ax = a * xdi;lll bx = b * xdi;lll ay = a * ydi;lll by = b * ydi;if (ax && bx) {return less(-ay, -ax, -by, -bx);}if (!ax && !bx) {return (ay > 0) > (by > 0);}if (ax && !bx) {return by < 0;}if (!ax && bx) {return ay > 0;}return false;});vecd u = normalize(vecd(p[stack1.front()] * xdir, p[stack1.front()] * ydir, 0));vecd v = normalize(vecd(p[stack1.back()] * xdir, p[stack1.back()] * ydir, 0));std::printf("%.12lf\n", lf(llf(1) - myacos(u * v) / pi / llf(2)));return 0;}}}for (ul i = 1; i <= n; ++i) {p2[i] = vec(p[i] * xdi, p[i] * ydi, p[i] * zdi);}stack1.resize(0);for (ul i = 1; i <= n; ++i) {stack1.push_back(i);}gethulld(stack1, stackbuttom, stacktop);llf ans = 0;for (ul i = 0; i + 2 < stackbuttom.size(); ++i) {heap.push(cnt(p[stackbuttom[i]], p[stackbuttom[i + 1]], p[stackbuttom[i + 2]]));}for (ul i = 0; i + 2 < stacktop.size(); ++i) {heap.push(cnt(p[stacktop[i]], p[stacktop[i + 1]], p[stacktop[i + 2]]));}heap.push(cnt(p[stackbuttom[stackbuttom.size() - 2]], p[stacktop[0]], p[stacktop[1]]));heap.push(cnt(p[stacktop[stacktop.size() - 2]], p[stackbuttom[0]], p[stackbuttom[1]]));while (heap.size() >= 2) {llf a = heap.top();heap.pop();llf b = heap.top();heap.pop();heap.push(a + b);}ans = heap.top() + pi + pi;std::printf("%.12lf\n", lf(ans / pi / llf(4)));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 T;ul n, c;ul sz;const ul mxsz = 1 << 19;const ul maxn = 5e5;ul fac[maxn + 1];ul v[maxn + 1];ul tree[mxsz << 1];ul query(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 = v[ret] < v[tree[l ^ 1]] ? ret : tree[l ^ 1];}if (r & 1) {ret = v[ret] < v[tree[r ^ 1]] ? ret : tree[r ^ 1];}}return ret;}void change(ul pos, ul val){v[pos] = val;for (pos |= sz, pos >>= 1; pos; pos >>= 1) {tree[pos] = v[tree[pos << 1]] < v[tree[pos << 1 | 1]] ? tree[pos << 1] : tree[pos << 1 | 1];}}void build(ul n){sz = 1;while (n + 2 > sz) {sz <<= 1;}tree[sz] = 0;for (ul i = 1; i <= n; ++i) {tree[sz | i] = i;}for (ul i = n + 1; i != sz; ++i) {tree[sz | i] = 0;}for (ul i = sz - 1; i; --i) {tree[i] = v[tree[i << 1]] < v[tree[i << 1 | 1]] ? tree[i << 1] : tree[i << 1 | 1];}}ul search(ul l, ul r, ul x, ul y){if (r - l + 1 < (x + y) * c) {return fac[r - l + 1 - std::max(x, ul(1)) + 1 - std::max(y, ul(1)) + 1];}ul cut = query(l, r);if (cut + 1 <= l + x * c) {change(cut, maxn + 1);return mul(x * c - (x - 1), search(l, r, x + 1, y));}if (cut + y * c >= r + 1) {change(cut, maxn + 1);return mul(y * c - (y - 1), search(l, r, x, y + 1));}return mul(search(l, cut - 1, x, cut - l >= c ? 1 : 0), search(cut + 1, r, r - cut >= c ? 1 : 0, y));}int main(){fac[0] = 1;for (ul i = 1; i <= maxn; ++i) {fac[i] = mul(fac[i - 1], i);}std::scanf("%u", &T);v[0] = maxn + 1;for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u", &n, &c);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &v[i]);}build(n);std::printf("%u\n", search(1, n, 0, 0));}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 llf = long double;const ul maxn = 2e5;ul n, m;std::map<ul, ull> graph[maxn + 1];ul next(ul a, ul b){auto it = std::next(graph[b].find(a));return it == graph[b].end() ? graph[b].begin()->first : it->first;}class vec {public:ll x = 0;ll y = 0;vec()=default;vec(ll a, ll b): x(a), y(b) {}};vec operator+(const vec& a, const vec& b){return vec(a.x + b.x, a.y + b.y);}vec operator-(const vec& a, const vec& b){return vec(a.x - b.x, a.y - b.y);}ll operator*(const vec& a, const vec& b){return a.x * b.x + a.y * b.y;}ll operator^(const vec& a, const vec& b){return a.x * b.y - a.y * b.x;}ul tot = 0;vec p[maxn + 1];const ll tau = 104653;ll lowersqrt(ll x){ll tmp = std::llround(std::sqrt(llf(x)));if (tmp * tmp > x) {--tmp;}return tmp;}std::mt19937_64 rnd;using pulul = std::pair<ul, ul>;class hashmap {public:class node {public:pulul key;ul val = 0;};bool ex[1 << 22];node v[1 << 22];ul sz;ul a;ul b;ul c;const ul mod = 1e9 + 7;void init(ul n){a = rnd() % (mod - 1) + 1;b = rnd() % (mod - 1) + 1;c = rnd() % mod;sz = 1;while (sz + sz < n + n + n) {sz <<= 1;}std::memset(ex, false, sz * sizeof(bool));}ul& operator[](const pulul& x){ul h = (ull(x.first) * ull(a) + ull(x.second) * ull(b) + ull(c)) % mod & sz - 1;while (true) {if (!ex[h]) {ex[h] = true;v[h].key = x;v[h].val = 0;return v[h].val;}if (v[h].key == x) {return v[h].val;}h = h + 1 & sz - 1;}}};hashmap state;ul stack[maxn + 1];using pullpulul = std::pair<ull, pulul>;std::priority_queue<pullpulul, std::vector<pullpulul>, std::greater<pullpulul>> heap;std::priority_queue<pullpulul> heap2;ul fa[maxn + 1];ul rk[maxn + 1];ul cnt[maxn + 1];ul getfather(ul x){return x == fa[x] ? x : fa[x] = getfather(fa[x]);}void connect(ul x, ul y){x = getfather(x);y = getfather(y);if (rk[x] < rk[y]) {fa[x] = y;cnt[y] += cnt[x];} else if (rk[x] > rk[y]) {fa[y] = x;cnt[x] += cnt[y];} else {fa[x] = y;cnt[y] += cnt[x];++rk[y];}}const ul mod = 998244353;ul plus(ul a, ul b){return a + b < mod ? a + b : a + b - mod;}ul mul(ul a, ul b){return ull(a) * ull(b) % mod;}int main(){rnd.seed(std::time(0));for (vec a(1, 0); a.x * a.x <= tau; ++a.x) {ll t = lowersqrt(tau - a.x * a.x);for (a.y = 0; a.y <= t; ++a.y) {if (std::__gcd(a.x, a.y < 0 ? -a.y : a.y) != 1) {continue;}++tot;p[tot] = a;}}std::sort(p + 1, p + tot + 1, [](const vec& a, const vec& b){return a.y * b.x < b.y * a.x;});for (ul i = tot + 1; i <= maxn; ++i) {p[i] = vec(-p[i - tot].y, p[i - tot].x);}for (ul i = 2; i <= maxn; ++i) {p[i] = p[i - 1] + p[i];}std::scanf("%u%u", &n, &m);for (ul i = 1; i <= m; ++i) {ul u, v;ull c;std::scanf("%u%u%llu", &u, &v, &c);graph[u][v] = c;graph[v][u] = c;}state.init(m + m);for (ul s = 1; s <= n; ++s) {for (auto& e : graph[s]) {ul t = e.first;if (state[pulul(s, t)]) {continue;}ul tot = 1;stack[1] = s;ll sum = 0;for (ul i = s, j = t; ; ) {sum += p[i] ^ p[j];if (j == s) {break;}++tot;stack[tot] = j;ul nexj = next(i, j);i = j;j = nexj;}stack[0] = stack[tot];ul tmp = sum < 0 ? 1 : 2;for (ul i = 1; i <= tot; ++i) {ul s = stack[i - 1];ul t = stack[i];if (tmp == 2) {heap.push(pullpulul(graph[s][t], pulul(s, t)));}state[pulul(s, t)] = tmp;}}}while (heap.size()) {auto c = heap.top();heap.pop();if (state[pulul(c.second.second, c.second.first)] == 2) {continue;}if (graph[c.second.first][c.second.second] != c.first) {continue;}for (ul i = c.second.first, j = next(c.second.second, c.second.first); j != c.second.first; ) {ull a = graph[i][j] += c.first;graph[j][i] += c.first;state[pulul(i, j)] = 2;heap.push(pullpulul(a, pulul(i, j)));ul nexj = next(i, j);i = j;j = nexj;}graph[c.second.first].erase(c.second.second);graph[c.second.second].erase(c.second.first);}for (ul i = 1; i <= n; ++i) {cnt[i] = 1;fa[i] = i;}for (ul i = 1; i <= n; ++i) {for (auto& e : graph[i]) {if (e.first > i) {break;}heap2.push(pullpulul(e.second, pulul(i, e.first)));}}ul ans = 0;while (heap2.size()) {auto c = heap2.top();heap2.pop();ul x = getfather(c.second.first);ul y = getfather(c.second.second);ans = plus(ans, mul(c.first % mod, mul(cnt[x], cnt[y])));connect(x, y);}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;const ul maxn = 1e5;ul n;li a[maxn + 1];li b[maxn + 1];bool al[maxn + 1];ll ans = 0;ul js[18];ll tans[1 << 17];li minus[1 << 17][17];int main(){std::scanf("%u", &n);for (ul i = 1; i <= n; ++i) {std::scanf("%d", &a[i]);}for (ul i = 1; i <= n; ++i) {std::scanf("%d", &b[i]);}ul tot = 31 - __builtin_clz(n);for (ul mask = 2; mask < (1 << tot + 1); mask += 2) {for (ul cmask = mask; cmask; cmask ^= 1 << __builtin_ctz(cmask)) {ul i = __builtin_ctz(cmask);for (ul j = i << 1; j <= tot; j += i) {if (mask >> j & 1) {++minus[mask][j];}}}}ans = a[1];for (ul i = 2; i <= n; ++i) {if (al[i]) {continue;}ul tot = 0;for (ull j = i; j <= n; j *= i) {++tot;js[tot] = j;al[j] = true;}ll mx = 0;tans[0] = 0;for (ul mask = 2; mask < (1 << tot + 1); mask += 2) {ul id = 31 - __builtin_clz(mask);tans[mask] = tans[mask ^ 1 << id] + a[js[id]];ll tt = tans[mask];for (ul j = 1; j <= tot; ++j) {tt -= ll(minus[mask][j]) * ll(b[js[j]]);}mx = std::max(mx, tt);}ans += mx;}std::printf("%lld\n", ans);return 0;}