@qq290637843
2021-03-10T13:44:44.000000Z
字数 20044
阅读 234
一共有十三道题,其中十道题在此处可以提交https://ac.nowcoder.com/acm/contest/7830。
另外三道题的题面可以找我qq联系要题面,这三道题中有两道我有数据,但给我数据的人要求不外传,所以我只能帮忙代运行代码。
简单题
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;std::set<ul> set;int main(){ull ans = 0;ul n;std::scanf("%u", &n);for (ul i = 1; i <= n; ++i) {ul a;std::scanf("%u", &a);auto it = std::next(set.insert(a).first);if (it != set.end()) {ans += *it;}}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;using lf = double;using llf = long double;ul n, m, s, t;const ul maxn = 200;class edge_t {public:llf x = 0;llf y = 0;ul to = 0;edge_t()=default;edge_t(ul a, llf b, llf c): to(a), x(b), y(c) {}};class ach_t {public:llf dis = 0;ul to = 0;ach_t()=default;ach_t(ul a, llf b): to(a), dis(b) {}};bool operator<(const ach_t& a, const ach_t& b){return a.dis > b.dis;}std::vector<edge_t> edges[maxn + 1];const llf inf = 1e15;void calc(llf a, llf& ans, llf& dans){static llf dis[maxn + 1];static llf ddis[maxn + 1];static bool al[maxn + 1];static std::priority_queue<ach_t> heap;for (ul i = 1; i <= n; ++i) {dis[i] = inf;al[i] = false;}dis[s] = 0;ddis[s] = 0;heap.push(ach_t(s, 0));while (heap.size()) {auto curr = heap.top();heap.pop();if (al[curr.to]) {continue;}al[curr.to] = true;for (const auto& e : edges[curr.to]) {llf newdis = a * e.y + e.x + curr.dis;if (newdis < dis[e.to]) {dis[e.to] = newdis;ddis[e.to] = ddis[curr.to] + e.y;heap.push(ach_t(e.to, newdis));}}}ans = dis[t];dans = ddis[t];}class point {public:llf a = 0;llf dis = 0;llf ddis = 0;point()=default;point(llf x, llf y, llf z): a(x), dis(y), ddis(z) {}};std::vector<point> stack;std::priority_queue<llf, std::vector<llf>, std::greater<llf>> heap;const llf eps = 1e-4;int main(){std::scanf("%u%u%u%u", &n, &m, &s, &t);for (ul i = 1; i <= m; ++i) {ul u, v;lf x, y;std::scanf("%u%u%lf%lf", &u, &v, &x, &y);edges[u].push_back(edge_t(v, x, y));edges[v].push_back(edge_t(u, x, y));}llf tans, tdans;calc(0, tans, tdans);stack.push_back(point(0, tans, tdans));calc(1, tans, tdans);stack.push_back(point(1, tans, tdans));while (stack.size() >= 2) {auto p2 = stack.back();llf d2 = p2.ddis;llf y2 = p2.dis;llf x2 = p2.a;stack.pop_back();auto p1 = stack.back();llf d1 = p1.ddis;llf y1 = p1.dis;llf x1 = p1.a;if (ll(d2) == ll(d1)) {heap.push((y1 + y2) * (x2 - x1) * llf(0.5));continue;}point p3;llf kk = x2 - x1;llf sp = -(-d1 * kk + (y2 - y1)) * (-d2 * kk + (y2 - y1)) / (d1 - d2) / kk;if (sp <= eps) {heap.push((y1 + y2) * (x2 - x1) * llf(0.5));continue;}p3.a = ((y2 - y1) + (x1 * d1 - x2 * d2)) / (d1 - d2);calc(p3.a, p3.dis, p3.ddis);stack.push_back(p3);stack.push_back(p2);}while (heap.size() >= 2) {auto a = heap.top();heap.pop();auto b = heap.top();heap.pop();heap.push(a + b);}std::printf("%.6lf\n", lf(heap.top()));return 0;}
第一个表达式的来源会用到https://chaoli.club/index.php/5490/
对于第个位置,使其好的数列数量为:
#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 n, L;const ul maxn = 1e5;const ul base = 998244353;const ul& mod = base;ul plus(ul a, ul b){return a + b < base ? a + b : a + b - base;}ul minus(ul a, ul b){return a < b ? a + base - b : a - b;}ul mul(ul a, ul b){return ull(a) * ull(b) % base;}void exgcd(li a, li b, li& x, li& y){if (b) {exgcd(b, a % b, y, x);y -= x * (a / b);} else {x = 1;y = 0;}}ul inverse(ul a){li x, y;exgcd(a, base, x, y);return x < 0 ? x + li(base) : x;}ul pow(ul a, ul b){ul ret = 1;ul temp = a;while (b) {if (b & 1) {ret = mul(ret, temp);}temp = mul(temp, temp);b >>= 1;}return ret;}class polynomial : public vul {public:void clearzero() {while (size() && !back()) {pop_back();}}polynomial()=default;polynomial(const vul& a): vul(a) { }polynomial(vul&& a): vul(std::move(a)) { }ul degree() const {return size() - 1;}ul operator()(ul x) const {ul ret = 0;for (ul i = size() - 1; ~i; --i) {ret = mul(ret, x);ret = plus(ret, vul::operator[](i));}return ret;}};polynomial& operator-=(polynomial& a, const polynomial& b){a.resize(std::max(a.size(), b.size()), 0);for (ul i = 0; i != b.size(); ++i) {a[i] = minus(a[i], b[i]);}a.clearzero();return a;}polynomial operator-(const polynomial& a, const polynomial& b){polynomial ret = a;return ret -= b;}class ntt_t {public:static const ul lgsz = 20;static const ul sz = 1 << lgsz;static const ul g = 3;ul w[sz + 1];ul leninv[lgsz + 1];ntt_t() {ul wn = pow(g, (base - 1) >> lgsz);w[0] = 1;for (ul i = 1; i <= sz; ++i) {w[i] = mul(w[i - 1], wn);}leninv[lgsz] = inverse(sz);for (ul i = lgsz - 1; ~i; --i) {leninv[i] = plus(leninv[i + 1], leninv[i + 1]);}}void operator()(vul& v, ul& n, bool inv) {ul lgn = 0;while ((1 << lgn) < n) {++lgn;}n = 1 << lgn;v.resize(n, 0);for (ul i = 0, j = 0; i != n; ++i) {if (i < j) {std::swap(v[i], v[j]);}ul k = n >> 1;while (k & j) {j &= ~k;k >>= 1;}j |= k;}for (ul lgmid = 0; (1 << lgmid) != n; ++lgmid) {ul mid = 1 << lgmid;ul len = mid << 1;for (ul i = 0; i != n; i += len) {for (ul j = 0; j != mid; ++j) {ul t0 = v[i + j];ul t1 = mul(w[inv ? (len - j << lgsz - lgmid - 1) : (j << lgsz - lgmid - 1)], v[i + j + mid]);v[i + j] = plus(t0, t1);v[i + j + mid] = minus(t0, t1);}}}if (inv) {for (ul i = 0; i != n; ++i) {v[i] = mul(v[i], leninv[lgn]);}}}} ntt;polynomial& operator*=(polynomial& a, const polynomial& b){if (!b.size() || !a.size()) {a.resize(0);return a;}polynomial temp = b;ul npmp1 = a.size() + b.size() - 1;if (ull(a.size()) * ull(b.size()) <= ull(npmp1) * ull(50)) {temp.resize(0);temp.resize(npmp1, 0);for (ul i = 0; i != a.size(); ++i) {for (ul j = 0; j != b.size(); ++j) {temp[i + j] = plus(temp[i + j], mul(a[i], b[j]));}}a = temp;a.clearzero();return a;}ntt(a, npmp1, false);ntt(temp, npmp1, false);for (ul i = 0; i != npmp1; ++i) {a[i] = mul(a[i], temp[i]);}ntt(a, npmp1, true);a.clearzero();return a;}polynomial operator*(const polynomial& a, const polynomial& b){polynomial ret = a;return ret *= b;}polynomial& operator*=(polynomial& a, ul b){if (!b) {a.resize(0);return a;}for (ul i = 0; i != a.size(); ++i) {a[i] = mul(a[i], b);}return a;}polynomial operator*(const polynomial& a, ul b){polynomial ret = a;return ret *= b;}polynomial inverse(const polynomial& a, ul lgdeg){polynomial ret({inverse(a[0])});polynomial temp;polynomial tempa;for (ul i = 0; i != lgdeg; ++i) {tempa.resize(0);tempa.resize(1 << i << 1, 0);for (ul j = 0; j != tempa.size() && j != a.size(); ++j) {tempa[j] = a[j];}temp = ret * (polynomial({2}) - tempa * ret);if (temp.size() > (1 << i << 1)) {temp.resize(1 << i << 1, 0);}temp.clearzero();std::swap(temp, ret);}return ret;}ul fac[maxn + 1];ul fiv[maxn + 1];polynomial p1, p2, p3;ul binomial(ul a, ul b){return mul(fac[a], mul(fiv[b], fiv[a - b]));}int main(){std::scanf("%u%u", &n, &L);L %= mod;fac[0] = 1;for (ul i = 1; i <= n; ++i) {fac[i] = mul(fac[i - 1], i);}fiv[n] = inverse(fac[n]);for (ul i = n; i; --i) {fiv[i - 1] = mul(fiv[i], i);}p1.resize(n);p2.resize(n);for (ul i = 1, Li = L; i <= n; ++i, Li = mul(Li, L)) {p1[i - 1] = mul(Li, fiv[i]);p2[i - 1] = fiv[i];}p2 = inverse(p2, 32 - __builtin_clz(n - 1));p2.resize(n);p3 = p1 * p2;p3.resize(n);p1.resize(n);p2.resize(n);for (ul r = n - 1, Lnm1mr = 1; r >= 1; --r, Lnm1mr = mul(Lnm1mr, L)) {p1[r] = mul(mul(mul(mul(p3[r], fac[r]), binomial(n, r + 1)), Lnm1mr), fac[r - 1]);if (r & 1) {p1[r] = minus(0, p1[r]);}p2[r] = fiv[r];}p2[0] = fiv[0];std::reverse(p1.begin(), p1.end());p3 = p1 * p2;p3.resize(n);std::reverse(p3.begin(), p3.end());for (ul k = 1; k <= n - 1; ++k) {p3[k] = mul(p3[k], fiv[k - 1]);if (k & 1) {p3[k] = minus(0, p3[k]);}std::printf("%u ", p3[k]);}std::printf("0\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;ul n;const ul maxn = 1e5;ul a[maxn + 1];ul mn = 1e9;ul cnt[11];int main(){std::scanf("%u", &n);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &a[i]);mn = std::min(mn, a[i]);}for (ul i = 1; i <= n; ++i) {a[i] -= mn;++cnt[a[i]];}llf sum = 0;for (ul i = 10; ~i; --i) {sum = sum * std::exp(llf(1));sum += llf(cnt[i]);}for (ul i = 1; i <= n; ++i) {if (i != 1) {std::putchar(' ');}std::printf("%.8lf", std::exp(llf(a[i])) / sum);}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;using lf = double;ul T;ul n;const ul maxn = 1e4;llf R, r;llf in(){lf tmp;std::scanf("%lf", &tmp);return tmp;}void calc(llf a, llf b, llf c, llf& ans1, llf& ans2){llf delta = std::max(b * b - llf(4) * a * c, llf(0));ans1 = (-b - std::sqrt(delta)) / (a + a);ans2 = (-b + std::sqrt(delta)) / (a + a);}ul tot;std::pair<llf, char> v[maxn + maxn + 1];int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);R = in();r = in();tot = 0;for (ul i = 1; i <= n; ++i) {llf x = in();llf y = in();llf rhos = std::sqrt((x - r) * (x - r) + y * y);llf costhetas = (x - r) / rhos;llf sinthetas = y / rhos;llf t1, t2;calc(r * r * R + R * rhos * rhos + 2 * r * R * rhos * costhetas, -4 * r * R * rhos * sinthetas, -r * r * r + 2 * r * r * R + r * rhos * rhos - 2 * r * R * rhos * costhetas, t1, t2);if (t1 > t2) {std::swap(t1, t2);}++tot;v[tot].first = t1;v[tot].second = '(';++tot;v[tot].first = t2;v[tot].second = ')';}std::sort(v + 1, v + n + n + 1);ul mx = 0;ul cnt = 0;for (ul i = 1; i <= n + n; ++i) {if (v[i].second == '(') {++cnt;mx = std::max(mx, cnt);} else if (v[i].second == ')') {--cnt;}}std::printf("%u\n", mx);}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;using lf = double;ul n;const ul maxn = 200;ll x[maxn + 1];ll y[maxn + 1];bool already[maxn + 1][maxn + 1];ul ans[maxn + 1][maxn + 1];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;}ul calc(ul l, ul r){if (already[l][r]) {return ans[l][r];}already[l][r] = true;if (l + 1 == r) {return ans[l][r] = 1;}for (ul m = l + 1; m + 1 <= r; ++m) {if ((x[r] - x[m]) * (y[l] - y[m]) - (x[l] - x[m]) * (y[r] - y[m]) > 0) {ans[l][r] = plus(ans[l][r], mul(calc(l, m), calc(m, r)));}}return ans[l][r];}int main(){std::scanf("%u", &n);ll sum = 0;for (ul i = 1; i <= n; ++i) {std::scanf("%lld%lld", &x[i], &y[i]);if (i != 1) {sum += x[i - 1] * y[i] - x[i] * y[i - 1];}}sum += x[n] * y[1] - x[1] * y[n];if (sum < 0) {std::reverse(x + 1, x + n + 1);std::reverse(y + 1, y + n + 1);}std::printf("%u\n", calc(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;const ul maxn = 2e5;ul d[maxn + 1];ul cnt = 0;int main(){std::scanf("%u", &n);for (ul i = 1; i <= n - 1; ++i) {ul a, b;std::scanf("%u%u", &a, &b);++d[a];++d[b];}for (ul i = 1; i <= n; ++i) {if (d[i] == 1) {++cnt;}}std::printf("%u\n", cnt);return 0;}
一个排列如果满足以下二条件之一,则称其为双调排列:
1、升降升,且首项大于等于尾项;
2、降升降,且首项小于等于尾项。
注意,升降、降升、升、降序列都复合以上要求。
现在考虑有一长为的双调序列,那么简单分类讨论可证(为了符合直观印象,建议画图),和都是长为的双调序列,且第一个序列的最大值小于等于第二个序列的最小值。由此可知,如果一个长为的序列一开始是双调的,那么只要经过次这样的合并过程就变成升序列了。
现在假设有一长的序列,其中前已经是升序,后已经是升序,那么显然和都是长为的双调序列(第一个显然是升降序列,第二个显然是降升序列,建议画图一眼看出),且第一个序列的最大值小于等于第二个序列的最小值,接着再使用上一段的结论可以得到长为的升序列。
#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;std::vector<std::pair<ul, ul>> a[106];void bisort(ul l, ul r, ul tot){if (l + 1 == r) {return;}++tot;for (ul i = l, j = r + l >> 1; j != r; ++i, ++j) {if (j < n) {a[tot].push_back(std::pair<ul, ul>(i, j));}}bisort(l, l + r >> 1, tot);bisort(l + r >> 1, r, tot);}void sort(ul l, ul r, ul tot){if (l + 1 == r) {return;}sort(l, l + r >> 1, tot - __builtin_ctz(r - l));sort(l + r >> 1, r, tot - __builtin_ctz(r - l));tot -= __builtin_ctz(r - l);++tot;for (ul i = l, j = r - 1; i < j; ++i, --j) {if (j < n) {a[tot].push_back(std::pair<ul, ul>(i, j));}}bisort(l, l + r >> 1, tot);bisort(l + r >> 1, r, tot);}int main(){std::scanf("%u", &n);ul tot = 0;ul k = 32 - __builtin_clz(n - 1);if (n == 1 || n == 0) {k = 0;}for (ul i = 1; i <= k; ++i) {tot += i;}sort(0, 1 << k, tot);std::printf("%u\n", tot);for (ul i = 1; i <= tot; ++i) {std::printf("%u\n", ul(a[i].size()));for (auto p : a[i]) {std::printf("%u %u\n", p.first, p.second);}}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;inline void swap(ul& a, ul& b){a ^= b ^= a ^= b;}class link_cut_tree {public:ul c[maxn + 1][2], fa[maxn + 1], top, q[maxn + 1], rev[maxn + 1];ull sum[maxn + 1];ul cnt;inline void init(ul n) {for (ul i = 1; i <= n; ++i) {c[i][0] = c[i][1] = fa[i] = rev[i] = sum[i] = 0;}cnt = 0;}inline void cfa(ul x, ul y) {if (fa[x]) {sum[fa[x]] ^= sum[x];}fa[x] = y;if (fa[x]) {sum[fa[x]] ^= sum[x];}}inline void pushdown(ul x) {if (rev[x]) {ul l = c[x][0], r = c[x][1];rev[l] ^= 1, rev[r] ^= 1, rev[x] ^= 1;swap(c[x][0], c[x][1]);}}inline bool isroot(ul x) {return c[fa[x]][0] != x && c[fa[x]][1] != x;}inline void rotate(ul x) {ul y = fa[x], z = fa[y], l, r;l = c[y][0] != x;r = l ^ 1;if (!isroot(y)) {c[z][c[z][0] != y] = x;}ull tmp1 = sum[x] ^ sum[c[x][r]];ull tmp2 = sum[y] ^ sum[x];sum[y] ^= tmp1;sum[x] ^= tmp2;fa[x] = z;fa[y] = x;fa[c[x][r]] = y;c[y][l] = c[x][r];c[x][r] = y;}inline void splay(ul x) {top = 1;q[top] = x;for (ul i = x; !isroot(i); i = fa[i]) {q[++top] = fa[i];}for (ul i = top; i; --i) {pushdown(q[i]);}while (!isroot(x)) {ul y = fa[x], z = fa[y];if (!isroot(y)) {rotate((c[y][0] == x) != (c[z][0] == y) ? x : y);}rotate(x);}}inline void access(ul x) {ul xx = x;for (ul t = 0; x; t = x, x = fa[x]) {splay(x);c[x][1] = t;}splay(xx);}inline void evert(ul x) {access(x);rev[x] ^= 1;}inline void cut(ul x, ul y) {evert(x);if (sum[x]) {--cnt;}access(y);c[y][0] = 0;cfa(x, 0);access(x);if (sum[x]) {++cnt;}access(y);if (sum[y]) {++cnt;}}inline void link(ul x, ul y) {evert(x);if (sum[x]) {--cnt;}access(y);if (sum[y]) {--cnt;}cfa(x, y);if (sum[y]) {++cnt;}}inline void change(ul x, ull v) {access(x);if (sum[x]) {--cnt;}sum[x] ^= v;if (sum[x]) {++cnt;}}};link_cut_tree tree;ul T;ul n, q;std::map<ull, ull> w;std::mt19937_64 rnd;int main(){rnd.seed(std::time(0));std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u", &n, &q);tree.init(n);for (ul i = 1; i <= q; ++i) {ul Type;std::scanf("%u", &Type);if (Type != 5) {ul u, v;std::scanf("%u%u", &u, &v);if (Type == 1) {tree.link(u, v);} else if (Type == 2) {tree.cut(u, v);} else if (Type == 3) {ull t = w[ull(u) << 32 | v] = rnd();tree.change(u, t);tree.change(v, t);} else if (Type == 4) {ull t = w[ull(u) << 32 | v];tree.change(u, t);tree.change(v, t);}} else {std::printf(tree.cnt ? "NO\n" : "YES\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 vul = std::vector<ul>;ul n;const ul base = 998244353;ul plus(ul a, ul b){return a + b < base ? a + b : a + b - base;}ul minus(ul a, ul b){return a < b ? a + base - b : a - b;}ul mul(ul a, ul b){return ull(a) * ull(b) % base;}void exgcd(li a, li b, li& x, li& y){if (b) {exgcd(b, a % b, y, x);y -= x * (a / b);} else {x = 1;y = 0;}}ul inverse(ul a){li x, y;exgcd(a, base, x, y);return x < 0 ? x + li(base) : x;}ul pow(ul a, ul b){ul ret = 1;ul temp = a;while (b) {if (b & 1) {ret = mul(ret, temp);}temp = mul(temp, temp);b >>= 1;}return ret;}class polynomial : public vul {public:void clearzero() {while (size() && !back()) {pop_back();}}polynomial()=default;polynomial(const vul& a): vul(a) { }polynomial(vul&& a): vul(std::move(a)) { }ul degree() const {return size() - 1;}ul operator()(ul x) const {ul ret = 0;for (ul i = size() - 1; ~i; --i) {ret = mul(ret, x);ret = plus(ret, vul::operator[](i));}return ret;}};polynomial& operator+=(polynomial& a, const polynomial& b){a.resize(std::max(a.size(), b.size()), 0);for (ul i = 0; i != b.size(); ++i) {a[i] = plus(a[i], b[i]);}a.clearzero();return a;}polynomial operator+(const polynomial& a, const polynomial& b){polynomial ret = a;return ret += b;}polynomial& operator-=(polynomial& a, const polynomial& b){a.resize(std::max(a.size(), b.size()), 0);for (ul i = 0; i != b.size(); ++i) {a[i] = minus(a[i], b[i]);}a.clearzero();return a;}polynomial operator-(const polynomial& a, const polynomial& b){polynomial ret = a;return ret -= b;}class ntt_t {public:static const ul lgsz = 20;static const ul sz = 1 << lgsz;static const ul g = 3;ul w[sz + 1];ul leninv[lgsz + 1];ntt_t() {ul wn = pow(g, (base - 1) >> lgsz);w[0] = 1;for (ul i = 1; i <= sz; ++i) {w[i] = mul(w[i - 1], wn);}leninv[lgsz] = inverse(sz);for (ul i = lgsz - 1; ~i; --i) {leninv[i] = plus(leninv[i + 1], leninv[i + 1]);}}void operator()(vul& v, ul& n, bool inv) {ul lgn = 0;while ((1 << lgn) < n) {++lgn;}n = 1 << lgn;v.resize(n, 0);for (ul i = 0, j = 0; i != n; ++i) {if (i < j) {std::swap(v[i], v[j]);}ul k = n >> 1;while (k & j) {j &= ~k;k >>= 1;}j |= k;}for (ul lgmid = 0; (1 << lgmid) != n; ++lgmid) {ul mid = 1 << lgmid;ul len = mid << 1;for (ul i = 0; i != n; i += len) {for (ul j = 0; j != mid; ++j) {ul t0 = v[i + j];ul t1 = mul(w[inv ? (len - j << lgsz - lgmid - 1) : (j << lgsz - lgmid - 1)], v[i + j + mid]);v[i + j] = plus(t0, t1);v[i + j + mid] = minus(t0, t1);}}}if (inv) {for (ul i = 0; i != n; ++i) {v[i] = mul(v[i], leninv[lgn]);}}}} ntt;polynomial& operator*=(polynomial& a, const polynomial& b){if (!b.size() || !a.size()) {a.resize(0);return a;}polynomial temp = b;ul npmp1 = a.size() + b.size() - 1;if (ull(a.size()) * ull(b.size()) <= ull(npmp1) * ull(50)) {temp.resize(0);temp.resize(npmp1, 0);for (ul i = 0; i != a.size(); ++i) {for (ul j = 0; j != b.size(); ++j) {temp[i + j] = plus(temp[i + j], mul(a[i], b[j]));}}a = temp;a.clearzero();return a;}ntt(a, npmp1, false);ntt(temp, npmp1, false);for (ul i = 0; i != npmp1; ++i) {a[i] = mul(a[i], temp[i]);}ntt(a, npmp1, true);a.clearzero();return a;}polynomial operator*(const polynomial& a, const polynomial& b){polynomial ret = a;return ret *= b;}polynomial& operator*=(polynomial& a, ul b){if (!b) {a.resize(0);return a;}for (ul i = 0; i != a.size(); ++i) {a[i] = mul(a[i], b);}return a;}polynomial operator*(const polynomial& a, ul b){polynomial ret = a;return ret *= b;}polynomial inverse(const polynomial& a, ul lgdeg){polynomial ret({inverse(a[0])});polynomial temp;polynomial tempa;for (ul i = 0; i != lgdeg; ++i) {tempa.resize(0);tempa.resize(1 << i << 1, 0);for (ul j = 0; j != tempa.size() && j != a.size(); ++j) {tempa[j] = a[j];}temp = ret * (polynomial({2}) - tempa * ret);if (temp.size() > (1 << i << 1)) {temp.resize(1 << i << 1, 0);}temp.clearzero();std::swap(temp, ret);}return ret;}polynomial v;int main(){std::scanf("%u", &n);v.resize(n);v[0] = 1;for (ul k = 1; k * (3 * k - 1) <= 2 * (n - 1); ++k) {ul t;t = (k & 1) ? minus(0, 1) : ul(1);if (k * (3 * k + 1) / 2 <= n - 1) {v[k * (3 * k + 1) >> 1] = t;}v[k * (3 * k - 1) >> 1] = t;}v = inverse(v, n - 1 ? ul(32 - __builtin_clz(n - 1)) : ul(0));v.resize(n);std::printf("%u\n", v[n - 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;ul n, m;const ul maxn = 300000;ul T;ul a[maxn + 1];int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u", &n, &m);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &a[i]);}ull l = 0, r = ull(1e9) * ull(n) / ull(m) + 1;while (l + 1 != r) {ull mid = l + r >> 1;ul Q = 0;ull R = 0;for (ul i = 1; i <= n; ++i) {if (a[i] >= mid) {++Q;} else {R += a[i];if (R >= mid) {R -= mid;++Q;}}}if (Q >= m) {l = mid;} else {r = mid;}}std::printf("%llu\n", l);}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 uss = std::uint8_t;const ul maxlen = 2e5;ul T;class pam_t {public:ul las;class node {public:ul ch[26];ul len = 0;ul fa = 0;ul anc = 0;node()=default;node(ul a, ul b): len(a), fa(b) {std::memset(ch, 0, sizeof(ch));}};std::vector<node> st = std::vector<node>(maxlen + 2);std::vector<uss> str = std::vector<uss>(maxlen + 1);ul newnode(ul len, ul fail = 0) {st.push_back(node(len, fail));return st.size() - 1;}ul getfail(ul x, ul n) {while (str[n - st[x].len - 1] != str[n]) {x = st[x].fa;}return x;}bool add(ul c) {ul i = str.size();str.push_back(c);ul cur = getfail(las, i);bool flag = false;if (!st[cur].ch[c]) {ul nw = newnode(st[cur].len + 2, st[getfail(st[cur].fa, i)].ch[c]);st[cur].ch[c] = nw;st[nw].anc = st[nw].len - st[st[nw].fa].len != st[st[nw].fa].len - st[st[st[nw].fa].fa].len ? st[nw].fa : st[st[nw].fa].anc;flag = true;}las = st[cur].ch[c];return flag;}void init() {str.resize(0);str.resize(1, 26);st.resize(0);newnode(0, 1);st[1].anc = 0;newnode(-1, 0);las = 0;}};pam_t pam;char str[maxlen + 2];li f[maxlen + 1][4];li g[maxlen + 1][3];ul gdiff[maxlen + 1][3];ul Case;li getg(li x, ul y, li diff, li fx){if (x == fx) {return f[x][y] - x;}if (gdiff[x][y] == diff) {return g[x][y];}gdiff[x][y] = diff;return g[x][y] = std::max(f[x][y] - x, getg(x - diff, y, diff, fx));}int main(){std::scanf("%u", &T);for (Case = 1; Case <= T; ++Case) {pam.init();std::scanf("%s", str + 1);li len = std::strlen(str + 1);for (li x = 1; x <= len; ++x) {pam.add(str[x] - 'a');gdiff[x][0] = gdiff[x][1] = gdiff[x][2] = 0;for (ul y = 1; y <= 3; ++y) {f[x][y] = f[x - 1][y];for (ul las = pam.las; las; las = pam.st[las].anc) {li diff = pam.st[las].len - pam.st[pam.st[las].fa].len;li z = x - pam.st[pam.st[las].anc].len - diff;li fz = x - pam.st[las].len;f[x][y] = std::max(f[x][y], x + getg(z, y - 1, diff, fz));}}}std::printf("%u\n", f[len][3]);}return 0;}