@qq290637843
2022-04-08T08:43:50.000000Z
字数 34546
阅读 384
题目见https://www.jisuanke.com/contest/6562/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;ul T;ull l, r, s;int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%llu%llu%llu", &l, &r, &s);ull ans;ull len = r - l + 1;if (r - l + 1 == 1) {if (s >= l) {ans = len;} else {ans = len - 1;}} else {if (((~r & 1) * r ^ (l & 1) * l ^ (len - (~r & 1) - (l & 1) >> 1 & 1)) <= s) {ans = len;} else {if (s >= 1) {if (l & 1) {if (r & 1) {ans = len - 1;} else {ans = (l ^ (len - 2 >> 1 & 1)) <= s ? len - 1 : len - 2;}} else {if (r & 1) {ans = len;} else {ans = len - 1;}}} else {if (l & 1) {if (r & 1) {if ((len & 3) == 3) {if (l == 1) {ans = len;} else {ans = len - 3;}} else {ans = len - 1;}} else {if ((len & 3) == 0) {if (l == 1) {ans = len - 1;} else {ans = len - 4;}} else {ans = len - 2;}}} else {if (r & 1) {if ((len & 3) == 0) {ans = len;} else {ans = len - 2;}} else {if ((len & 3) == 3) {ans = len - 3;} else {ans = len - 1;}}}}}}if (ans) {std::printf("%llu\n", ans);} else {std::printf("-1\n");}}return 0;}
换成另一个描述:求如下图的有向哈密顿路的个数,点被编号为,其中两点之间有边当且仅当。于是可以状态压缩动态规划,由此可知固定时,此关于为线性递推数列。所以可以先算出一些前项然后伯莱坎普梅西。
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;inline ull gfmul(ull a, ull b){auto vc = _mm_clmulepi64_si128(_mm_cvtsi64_si128(a), _mm_cvtsi64_si128(b), 0);auto vf = _mm_xor_si128(_mm_cvtsi64_si128(_mm_cvtsi128_si64(vc)), _mm_clmulepi64_si128(_mm_srli_si128(vc, 8), _mm_cvtsi64_si128(27ull), 0));return _mm_cvtsi128_si64(_mm_xor_si128(_mm_cvtsi64_si128(_mm_cvtsi128_si64(vf)), _mm_clmulepi64_si128(_mm_srli_si128(vf, 8), _mm_cvtsi64_si128(27ull), 0)));}ull X, Y;std::mt19937_64 rnd;ull gethash(const std::vector<ul>& v){ull ret = 1;for (ul i = 0; i != v.size(); i += 2) {ret = gfmul(ret, Y ^ gfmul(X ^ v[i], X ^ v[i + 1]));}return ret;}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;}class counter {public:std::vector<ul> v;ul cnt = 0;counter()=default;counter(const std::vector<ul>& a, ul b): v(a), cnt(b) {}counter(std::vector<ul>&& a, ul b): v(std::move(a)), cnt(b) {}};const ul maxn2 = 1e6;const ul maxn = 100;const ul maxk = 3;std::unordered_map<ull, counter> map[maxn + 1];void regular(std::vector<ul>& v, ul n, ul k){for (ul i = 0; i != v.size(); ++i) {if (v[i] + k <= n) {v[i] = 0;}}}std::vector<ul> nextcon;bool check(std::vector<ul>& v){ul cnt = 0;for (ul u : v) {if (!u) {++cnt;if (cnt == 3) {return false;}}}return true;}ul ans[maxk + 1][maxn2 + 1];ul bm(const ul s[], ul cc[], ul nn){static ul bb[1000];static ul tt[1000];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 cc[maxk + 1][1000];ul len[maxk + 1];ul T;int main(){rnd.seed(std::time(0));X = rnd();Y = rnd();ans[1][0] = 1;ans[2][0] = 1;ans[2][1] = 1;ans[3][0] = 1;ans[3][1] = 1;ans[3][2] = 2;for (ul k = 1; k <= 3; ++k) {map[k].clear();if (k == 1) {map[k][gethash({1, 1})] = counter({1, 1}, 1);} else if (k == 2) {map[k][gethash({1, 1, 2, 2})] = counter({1, 1, 2, 2}, 1);map[k][gethash({1, 2})] = counter({1, 2}, 1);} else if (k == 3) {map[k][gethash({1, 1, 2, 2, 3, 3})] = counter({1, 1, 2, 2, 3, 3}, 1);map[k][gethash({1, 2, 3, 3})] = counter({1, 2, 3, 3}, 1);map[k][gethash({1, 3, 2, 2})] = counter({1, 3, 2, 2}, 1);map[k][gethash({2, 3, 1, 1})] = counter({2, 3, 1, 1}, 1);map[k][gethash({1, 2})] = counter({1, 2}, 1);map[k][gethash({1, 3})] = counter({1, 3}, 1);map[k][gethash({2, 3})] = counter({2, 3}, 1);}for (ul n = k; n + 1 <= maxn; ++n) {map[n + 1].clear();for (const auto& p : map[n]) {const auto& con = p.second.v;ul val = p.second.cnt;for (ul i = 0; i + 1 != con.size(); ++i) {if (!con[i]) {continue;}if ((i & 1) && con[i - 1] == con[i]) {continue;}for (ul j = i + 1; j != con.size(); ++j) {if (!con[j]) {continue;}if ((j & 1) && con[j - 1] == con[j]) {continue;}if ((i >> 1) == (j >> 1)) {continue;}nextcon.resize(0);nextcon.push_back(con[i ^ 1]);nextcon.push_back(con[j ^ 1]);for (ul a = 0; a != con.size(); a += 2) {if ((a >> 1) != (i >> 1) && (a >> 1) != (j >> 1)) {nextcon.push_back(con[a]);nextcon.push_back(con[a + 1]);}}regular(nextcon, n + 1, k);if (!check(nextcon)) {continue;}auto& next = map[n + 1][gethash(nextcon)];next.v = nextcon;next.cnt = plus(next.cnt, val);}}for (ul i = 0; i != con.size(); ++i) {if (!con[i]) {continue;}if ((i & 1) && con[i - 1] == con[i]) {continue;}nextcon = con;nextcon[i] = n + 1;regular(nextcon, n + 1, k);if (!check(nextcon)) {continue;}auto& next = map[n + 1][gethash(nextcon)];next.v = nextcon;next.cnt = plus(next.cnt, val);}nextcon = con;nextcon.push_back(n + 1);nextcon.push_back(n + 1);regular(nextcon, n + 1, k);if (!check(nextcon)) {continue;}auto& next = map[n + 1][gethash(nextcon)];next.v = nextcon;next.cnt = plus(next.cnt, val);}}for (ul n = k; n <= maxn; ++n) {for (const auto& p : map[n]) {if (p.second.v.size() == 2) {ans[k][n] = plus(ans[k][n], p.second.cnt);}}if (n != 1) {ans[k][n] = mul(2, ans[k][n]);}}}for (ul k = 1; k <= 3; ++k) {len[k] = bm(ans[k], cc[k], maxn + 1);for (ul n = maxn + 1; n <= maxn2; ++n) {for (ul i = 1; i <= len[k]; ++i) {ans[k][n] = minus(ans[k][n], mul(cc[k][i], ans[k][n - i]));}}}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {ul n, k;std::scanf("%u%u", &n, &k);std::printf("%u\n", ans[k][n]);}return 0;}
简单题
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul T;ul l, r;ul mul(ul a, ul b, ul c){return ull(a) * ull(b) % c;}ul pow(ul a, ul b, ul c){ul ret = 1 % c;while (b) {if (b & 1) {ret = mul(ret, a, c);}a = mul(a, a, c);b >>= 1;}return ret;}std::mt19937 rnd;bool isprime(ul x){if (x == 1) {return true;}if (x == 2) {return true;}if (~x & 1) {return false;}ul t = __builtin_ctz(x - 1);ul s = x - 1 >> t;for (ul cnt = 1; cnt <= 20; ++cnt) {ul k = pow(rnd() % (x - 1) + 1, s, x);if (k == 1) {continue;}ul i = 0;while (k != 1 && k != x - 1 && i + 1 != t) {++i;k = mul(k, k, x);}if (k != x - 1) {return false;}}return true;}int main(){rnd.seed(std::time(0));std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u", &l, &r);if (r - l + 1 >= 420) {std::printf("Yes\n");continue;}ul x = 0;for (ul i = l; i <= r; ++i) {x += isprime(i);}std::printf(ull(x) * 3 < r - l + 1 ? "Yes\n" : "No\n");}return 0;}
首先,关于割的那刀这样处理:对任何一个用点棱存储的凸多面体,如果多加一个约束,只需要研究这个约束和那些点或者边相交了,就能得到一个新的用点棱存储的凸多面体。
现在解决给定一个点棱存储的凸多面体的体积问题。首先是要解决一个点所连出去的边的排序问题。这个问题这样解决,考虑先将所有点的重心找到,记为,接着,对每个点,将其连出去的边投影到和相垂直的平面上,于是就可以以为极点对边进行极角排序,这样就知道每次走完一条边之后,接下来哪条边才是“向左转”该走的了。于是可以求出所有面,再接着就是很简单的工作了。
过了,数据没有问题。
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.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 ull mod = 4179340454199820289ull;ull plus(ull a, ull b){return a + b < mod ? a + b : a + b - mod;}ull minus(ull a, ull b){return a < b ? a + mod - b : a - b;}ull mul(ll a, ll b){ll tmp = a * b - ll(llf(a) * llf(b) / llf(mod)) * ll(mod);return tmp < 0 ? tmp + ll(mod) : (tmp < ll(mod) ? tmp : tmp - ll(mod));}void exgcd(ll a, ll b, ll& x, ll& y){if (b) {exgcd(b, a % b, y, x);y -= a / b * x;} else {x = 1;y = 0;}}ull inverse(ull a){ll x, y;exgcd(a, mod, x, y);return x < 0 ? x + ll(mod) : x;}class hashllf {public:llf val = 0;ull hash = 0;hashllf()=default;hashllf(li x): val(x), hash((x + mod) % mod) {}hashllf(llf x): val(x), hash(0) {}hashllf(llf a, ull b): val(a), hash(b) {}operator llf() const {return val;}};hashllf operator+(const hashllf& a, const hashllf& b){return hashllf(a.val + b.val, plus(a.hash, b.hash));}hashllf operator-(const hashllf& a, const hashllf& b){return hashllf(a.val - b.val, minus(a.hash, b.hash));}hashllf operator*(const hashllf& a, const hashllf& b){return hashllf(a.val * b.val, mul(a.hash, b.hash));}hashllf operator/(const hashllf& a, const hashllf& b){return hashllf(a.val / b.val, mul(a.hash, inverse(b.hash)));}li sgn(const hashllf& x){return x.hash == 0 ? 0 : (x.val < 0 ? -1 : 1);}class vec {public:hashllf x = 0;hashllf y = 0;hashllf z = 0;vec()=default;vec(hashllf a, hashllf b, hashllf c): x(a), y(b), z(c) {}ul high() const {return sgn(x) ? 3 : (sgn(y) ? 2 : (sgn(z) ? 1 : 0));}hashllf& operator[](ul i) {return i == 1 ? z : (i == 2 ? y : x);}const hashllf& operator[](ul i) const {return i == 1 ? z : (i == 2 ? y : x);}};vec operator+(const vec& a, const vec& b){return vec(a.x + b.x, a.y + b.y, a.z + b.z);}vec operator-(const vec& a, const vec& b){return vec(a.x - b.x, a.y - b.y, a.z - b.z);}vec operator*(hashllf a, const vec& b){return vec(a * b.x, a * b.y, a * b.z);}vec operator*(const vec& a, hashllf b){return vec(a.x * b, a.y * b, a.z * b);}vec operator/(const vec& a, hashllf b){return vec(a.x / b, a.y / b, a.z / b);}hashllf operator*(const vec& a, const vec& b){return a.x * b.x + a.y * b.y + a.z * b.z;}ul n, m, k;ul totp;vec points[1 << 21];ul tote;std::pair<ul, ul> edges[1 << 21];std::vector<ul> pstack[4];std::vector<ul> estack[4];vec cutdir[4];vec cutx[4];vec cuty[4];hashllf cutbound[4];li type[1 << 21];std::vector<ul> tmpstack;std::priority_queue<llf, std::vector<llf>, std::greater<llf>> queue;llf myabs(llf x){return x < 0 ? -x : x;}class mygreater {public:bool operator()(llf a, llf b){return myabs(a) > myabs(b);}};std::priority_queue<llf, std::vector<llf>, mygreater> queue2;llf getsum(){while (queue2.size() >= 2) {llf a = queue2.top();queue2.pop();llf b = queue2.top();queue2.pop();queue2.push(a + b);}llf tmp = queue2.top();queue2.pop();return tmp;}vec getw(const std::vector<ul>& pstack){vec ret(0, 0, 0);for (auto p : pstack) {ret = ret + points[p];}ret = ret / hashllf(li(pstack.size()));for (auto p : pstack) {queue2.push(points[p].x);}ret.x.val = getsum() / llf(pstack.size());for (auto p : pstack) {queue2.push(points[p].y);}ret.y.val = getsum() / llf(pstack.size());for (auto p : pstack) {queue2.push(points[p].z);}ret.z.val = getsum() / llf(pstack.size());return ret;}hashllf vol1(const vec& a){return a * a;}hashllf vol2(const vec& a, const vec& b){hashllf aa = a * a;hashllf bb = b * b;hashllf ab = a * b;return aa * bb - ab * ab;}hashllf vol3(const vec& a, const vec& b, const vec& c){hashllf aa = a * a;hashllf ab = a * b;hashllf ac = a * c;hashllf bb = b * b;hashllf bc = b * c;hashllf cc = c * c;return aa * bb * cc + hashllf(2) * ab * bc * ac - ac * bb * ac - aa * bc * bc - ab * ab * cc;}hashllf vol3p(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.x * b.z * c.y - a.y * b.x * c.z - a.z * b.y * c.x;}void insert(std::vector<vec>& base, vec v){for (const auto u : base) {ul uh = u.high();if (sgn(v[uh])) {v = v - v[uh] / u[uh] * u;}}if (sgn(v.x) || sgn(v.y) || sgn(v.z)) {base.push_back(v);}}ul checkdim(const std::vector<ul>& pstack, vec& w){static std::vector<vec> base;base.resize(0);w = getw(pstack);for (auto p : pstack) {insert(base, points[p] - w);}return base.size();}ul region(llf x, llf y){return x < 0 ? (y < 0 ? 3 : 2) : (y < 0 ? 4 : 1);}std::vector<llf> ans;std::vector<ul> neibor[1 << 20];std::unordered_map<ull, ul> nextto;std::unordered_set<ull> already;ull base;std::mt19937_64 rnd;inline ull gfmul(ull a, ull b){auto vc = _mm_clmulepi64_si128(_mm_cvtsi64_si128(a), _mm_cvtsi64_si128(b), 0);auto vf = _mm_xor_si128(_mm_cvtsi64_si128(_mm_cvtsi128_si64(vc)), _mm_clmulepi64_si128(_mm_srli_si128(vc, 8), _mm_cvtsi64_si128(27ull), 0));return _mm_cvtsi128_si64(_mm_xor_si128(_mm_cvtsi64_si128(_mm_cvtsi128_si64(vf)), _mm_clmulepi64_si128(_mm_srli_si128(vf, 8), _mm_cvtsi64_si128(27ull), 0)));}std::set<ull> eset[4];void search(ul cutid){if (cutid == k + 1) {if (pstack[k].empty()) {ans.push_back(0);return;}vec w = getw(pstack[k]);for (ul p : pstack[k]) {neibor[p].resize(0);}for (const auto e : estack[k]) {neibor[edges[e].first].push_back(edges[e].second);neibor[edges[e].second].push_back(edges[e].first);}nextto.clear();for (auto p : pstack[k]) {vec z = points[p] - w;z = z / std::sqrt(z * z);vec sq;llf val = 0;for (auto q : neibor[p]) {llf newval = vol2(points[q] - points[p], z);if (val < newval) {sq = points[q];val = newval;}}vec x = sq - points[p];x = x - x * z * z;x = x / std::sqrt(x * x);vec y(z.y * x.z - z.z * x.y, z.z * x.x - z.x * x.z, z.x * x.y - z.y * x.x);sort(neibor[p].begin(), neibor[p].end(), [&](ul a, ul b) {llf ax = (points[a] - points[p]) * x;llf ay = (points[a] - points[p]) * y;llf bx = (points[b] - points[p]) * x;llf by = (points[b] - points[p]) * y;return region(ax, ay) != region(bx, by) ? region(ax, ay) < region(bx, by) : ax * by - ay * bx > 0;});neibor[p].push_back(neibor[p].front());for (ul i = 0; i + 1 != neibor[p].size(); ++i) {nextto[gfmul(base ^ neibor[p][i + 1], p)] = neibor[p][i];}}already.clear();while (queue.size()) {queue.pop();}for (auto p : pstack[k]) {neibor[p].pop_back();for (ul q : neibor[p]) {if (!already.insert(gfmul(base ^ p, q)).second) {continue;}for (ul i = q, j = nextto[gfmul(base ^ p, q)]; ; ) {queue.push(myabs(vol3p(points[p] - w, points[i] - w, points[j] - w)));ul newj = nextto[gfmul(base ^ i, j)];already.insert(gfmul(base ^ i, j));i = j;j = newj;if (j == p) {already.insert(gfmul(base ^ i, j));break;}}}}while (queue.size() >= 2) {llf a = queue.top();queue.pop();llf b = queue.top();queue.pop();queue.push(a + b);}ans.push_back(queue.top() / 6);return;}for (li pn : {1, -1}) {pstack[cutid].resize(0);estack[cutid].resize(0);eset[cutid].clear();if (pstack[cutid - 1].empty()) {search(cutid + 1);}tmpstack.resize(0);for (ul p : pstack[cutid - 1]) {type[p] = sgn(cutdir[cutid] * points[p] - cutbound[cutid]) * pn;if (type[p] <= 0) {pstack[cutid].push_back(p);}if (type[p] == 0) {tmpstack.push_back(p);}}for (ul e : estack[cutid - 1]) {if (type[edges[e].first] <= 0 && type[edges[e].second] <= 0) {estack[cutid].push_back(e);eset[cutid].insert(gfmul(edges[e].first ^ base, edges[e].second ^ base));}if (type[edges[e].first] * type[edges[e].second] < 0) {const auto& a = points[edges[e].first];const auto& b = points[edges[e].second];++totp;points[totp] = (cutbound[cutid] - a * cutdir[cutid]) / ((b - a) * cutdir[cutid]) * b + (cutbound[cutid] - b * cutdir[cutid]) / ((a - b) * cutdir[cutid]) * a;tmpstack.push_back(totp);pstack[cutid].push_back(totp);type[totp] = -1;++tote;edges[tote].first = type[edges[e].first] < type[edges[e].second] ? edges[e].first : edges[e].second;edges[tote].second = totp;estack[cutid].push_back(tote);eset[cutid].insert(gfmul(edges[tote].first ^ base, edges[tote].second ^ base));}}if (tmpstack.size()) {vec w;ul dim = checkdim(tmpstack, w);if (dim != 0) {llf val = 0;ul sp;for (ul p : tmpstack) {llf newval = vol1(points[p] - w);if (val < newval) {val = newval;sp = p;}}vec x = (points[sp] - w) / std::sqrt(vol1(points[sp] - w));vec z = cutdir[cutid] / std::sqrt(vol1(cutdir[cutid]));vec y(z.y * x.z - z.z * x.y, z.z * x.x - z.x * x.z, z.x * x.y - z.y * x.x);if (dim == 1) {std::sort(tmpstack.begin(), tmpstack.end(), [&](ul a, ul b){return points[a] * x < points[b] * x;});for (ul i = 0; i + 1 != tmpstack.size(); ++i) {if (eset[cutid].find(gfmul(tmpstack[i] ^ base, tmpstack[i + 1] ^ base)) == eset[cutid].end()) {++tote;edges[tote].first = tmpstack[i];edges[tote].second = tmpstack[i + 1];estack[cutid].push_back(tote);eset[cutid].insert(gfmul(edges[tote].first ^ base, edges[tote].second ^ base));}}} else if (dim == 2) {std::sort(tmpstack.begin(), tmpstack.end(), [&](ul a, ul b){llf ax = (points[a] - w) * x;llf ay = (points[a] - w) * y;llf bx = (points[b] - w) * x;llf by = (points[b] - w) * y;return region(ax, ay) != region(bx, by) ? region(ax, ay) < region(bx, by) : ax * by - ay * bx > 0;});tmpstack.push_back(tmpstack.front());for (ul i = 0; i + 1 != tmpstack.size(); ++i) {if (type[tmpstack[i]] != 0 || type[tmpstack[i + 1]] != 0) {++tote;edges[tote].first = tmpstack[i];edges[tote].second = tmpstack[i + 1];estack[cutid].push_back(tote);}}}}}if (pstack[cutid].size()) {vec w;ul dim = checkdim(pstack[cutid], w);if (dim < 3) {pstack[cutid].resize(0);}}search(cutid + 1);}}int main(){rnd.seed(std::time(0));base = rnd();std::scanf("%u%u%u", &n, &m, &k);for (ul i = 1; i <= n; ++i) {li x, y, z;std::scanf("%d%d%d", &x, &y, &z);points[totp] = vec(x, y, z);pstack[0].push_back(totp);++totp;}--totp;for (ul i = 1; i <= m; ++i) {++tote;std::scanf("%u%u", &edges[tote].first, &edges[tote].second);estack[0].push_back(tote);}for (ul i = 1; i <= k; ++i) {li a, b, c, d;std::scanf("%d%d%d%d", &a, &b, &c, &d);cutdir[i] = vec(a, b, c);cutbound[i] = d;}search(1);std::sort(ans.begin(), ans.end());for (const auto& a : ans) {std::printf("%.20Le\n", a);}return 0;}
简单题
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.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 T;ull plus(ull a, ull b, ull c){return a + b < c ? a + b : a + b - c;}ull minus(ull a, ull b, ull c){return a < b ? a + c - b : a - b;}ll mul(ll a, ll b, ll c){ll tmp = a * b - ll(llf(a) * llf(b) / llf(c)) * c;return tmp < 0 ? tmp + c : (tmp < c ? tmp : tmp - c);}ull pow(ull a, ull b, ull c){ull ret = 1 % c;while (b) {if (b & 1) {ret = mul(ret, a, c);}a = mul(a, a, c);b >>= 1;}return ret;}std::mt19937_64 rnd;bool isprime(ull x){if (x == 1) {return true;}if (x == 2) {return true;}if (~x & 1) {return false;}ul t = __builtin_ctzll(x - 1);ull s = x - 1 >> t;for (ul cnt = 1; cnt <= 20; ++cnt) {ull k = pow(rnd() % (x - 1) + 1, s, x);if (k == 1) {continue;}ul i = 0;while (k != 1 && k != x - 1 && i + 1 != t) {++i;k = mul(k, k, x);}if (k != x - 1) {return false;}}return true;}ull gcd(ull a, ull b){while (b) {b ^= a ^= b ^= a %= b;}return a;}ull rho(ull v){while (true) {ull c = rnd() % (v - 1) + 1;auto f = [&](ull x){return plus(mul(x, x, v), c, v);};ull x = rnd() % v;ull y = f(x);while (x != y) {ull tmp = gcd(minus(x, y, v), v);if (tmp != 1) {return tmp;}x = f(x);y = f(f(y));}}}std::vector<ull> facs;void getfact(ull x){static std::vector<ull> stack;stack.resize(0);facs.resize(0);if (x != 1) {stack.push_back(x);}while (stack.size()) {ull curr = stack.back();stack.pop_back();if (isprime(curr)) {facs.push_back(curr);} else {ull next = rho(curr);stack.push_back(next);stack.push_back(curr / next);}}std::sort(facs.begin(), facs.end());}ul n;ull a;ull x, y;std::vector<std::pair<ull, ull>> faccntx;std::vector<std::pair<ull, ull>> faccnty;int main(){rnd.seed(std::time(0));std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%llu%llu", &n, &x, &y);getfact(x);std::sort(facs.begin(), facs.end());faccntx.resize(0);for (auto p : facs) {if (faccntx.empty() || faccntx.back().first != p) {faccntx.push_back(std::pair<ull, ul>(p, 1));} else {++faccntx.back().second;}}faccnty = faccntx;for (auto& pc : faccnty) {ull p = pc.first;pc.second = 0;ull pi = p;ull tmp = y / p;while (true) {pc.second += y / pi;if (pi > tmp) {break;} else {pi *= p;}}}for (ul i = 1; i <= n; ++i) {std::scanf("%llu", &a);for (auto& pc : faccnty) {ull p = pc.first;ull pi = p;ull tmp = a / p;while (true) {pc.second -= a / pi;if (pi > tmp) {break;} else {pi *= p;}}}}ull ans = 2e18;for (ull i = 0; i != faccntx.size(); ++i) {ans = std::min(ans, faccnty[i].second / faccntx[i].second);}std::printf("%llu\n", ans);}return 0;}
简单题
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.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 ll maxv = 5000;const ll maxx = 200;std::string ans[maxx + 1];ll upcbrt(ll x){ll tmp = std::llround(std::cbrt(llf(x)));while (tmp * tmp * tmp < x) {++tmp;}return tmp;}std::string tmp;std::stringstream ss;int main(){for (ll a = -maxv, a3 = a * a * a; a3 * 3 <= maxx; ++a, a3 = a * a * a) {for (ll b = std::max(upcbrt(-maxv * maxv * maxv - a3), a), b3 = b * b * b; b <= maxv && a3 + b3 * 2 <= maxx; ++b, b3 = b * b * b) {for (ll c = std::max(upcbrt(-a * a * a - b * b * b), b), c3 = c * c * c; c <= maxv && a3 + b3 + c3 <= maxx; ++c, c3 = c * c * c) {ll v = a3 + b3 + c3;ss.str("");ss << a << ' ' << b << ' ' << c;tmp = ss.str();if (ans[v].empty() || ans[v].size() > tmp.size()) {std::swap(ans[v], tmp);}}}}std::freopen("Fdata.txt", "w", stdout);std::printf("{");for (ul i = 0; i <= maxx; ++i) {if (i) {std::printf(",");}std::cout << '\"' << ans[i] << '\"';}std::printf("}");return 0;}
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ll maxx = 200;std::string ans[maxx + 1] = {"0 0 0","0 0 1","0 1 1","1 1 1","","","-1 -1 2","-1 0 2","0 0 2","0 1 2","1 1 2","-2 -2 3","-11 7 10","","","-1 2 2","0 2 2","1 2 2","-2 -1 3","-2 0 3","-2 1 3","-86 28 85","","","2 2 2","-1 -1 3","-1 0 3","0 0 3","0 1 3","1 1 3","","","","","-6 5 5","0 2 3","1 2 3","-3 0 4","-3 1 4","","","","","2 2 3","-7 -5 8","-3 2 4","-2 3 3","-8 6 7","-2 -2 4","","","-796 602 659","","-1 3 3","0 3 3","1 3 3","-2 0 4","-2 1 4","","","-4 -1 5","-4 0 5","2 3 3","-1 0 4","0 0 4","0 1 4","1 1 4","","","-4 2 5","-64 23 63","-1 2 4","0 2 4","1 2 4","","","","","-55 26 53","-66 -49 74","2 2 4","3 3 3","-11 -11 14","-2 3 4","","","","-4126 -1972 4271","-4 3 5","-7 6 6","-1 3 4","0 3 4","1 3 4","-5 -5 7","","","-22 14 20","-3 -1 5","-3 0 5","2 3 4","-6 -3 7","-3 4 4","-239 118 229","","","-7 -4 8","-3 2 5","-48 -28 51","-1165 -948 1345","-2 -2 5","","-881 -296 892","","","","-12 8 11","-2 -1 5","-2 0 5","3 3 4","-6 -2 7","-2 4 4","","","-1 -1 5","-1 0 5","0 0 5","0 1 5","1 1 5","0 4 4","1 4 4","","","-1 2 5","0 2 5","1 2 5","-6 2 7","2 4 4","-11 -9 13","-86 -77 103","","","2 2 5","-7 -3 8","","-2 3 5","-8 -7 10","-9 -5 10","-56 -50 67","","","-367 260 317","-1 3 5","0 3 5","1 3 5","-6 3 7","3 4 4","","","","-130 80 119","2 3 5","-7 -2 8","-3 4 5","-76 -68 91","-66 -59 79","","","","-7 -1 8","-7 0 8","-7 1 8","-6 -5 8","","","-8 7 7","","","-7 2 8","-13 -10 15","3 3 5","","-2 4 5","-14 9 13","-17 10 16","","","-4 5 5","-58 27 56","-1 4 5","0 4 5","1 4 5","-6 4 7","4 4 4","","","","-7 3 8","2 4 5","-48 -19 49","-24 15 22","-2 -2 6"};ul T;ul x;int main(){std::cin >> T;for (ul Case = 1; Case <= T; ++Case) {std::cin >> x;std::cout << (ans[x].empty() ? std::string("impossible") : ans[x]) << std::endl;}return 0;}
下文中,原题是要在满足:
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.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;using d_t = lf;const ul maxn = 2e4;const ul maxk = 50;ul n, k;d_t t[maxn + 1][maxk + 1];d_t g[maxk + 1];d_t xchange[maxk + 1];bool gequal0;d_t M;d_t A;d_t T;d_t Acurr;const d_t beta = 0.00995;ull start;void f(d_t x[]){std::memset(g + 1, 0, sizeof(d_t) * k);d_t sum = 0;for (ul j = 1; j <= k; ++j) {sum += x[j];}for (ul j = 1; j <= k; ++j) {x[j] /= sum;}sum = 0;d_t gsum = 0;for (ul i = 1; i <= n; ++i) {d_t mn = t[i][1] * x[1];ul a = 1;for (ul j = 2; j <= k; ++j) {if (t[i][j] * x[j] < mn) {mn = t[i][j] * x[j];a = j;}}g[a] += t[i][a];sum += mn;}A = std::max(A, sum);Acurr = sum;T = (1 + beta) * A - Acurr;gequal0 = true;for (ul j = 1; j <= k; ++j) {gsum += g[j];g[j] *= k;if (g[j] != g[1]) {gequal0 = false;}}if (gequal0) {return;}for (ul j = 1; j <= k; ++j) {g[j] -= gsum;}d_t tmp = 0;for (ul j = 1; j <= k; ++j) {tmp += g[j] * g[j];}for (ul j = 1; j <= k; ++j) {xchange[j] = T * k * (g[j] / tmp);}}d_t x[maxk + 1];int main(){std::scanf("%u%u", &n, &k);for (ul i = 1; i <= n; ++i) {for (ul j = 1; j <= k; ++j) {ul tmp;std::scanf("%u", &tmp);t[i][j] = tmp;}}for (ul j = 1; j <= k; ++j) {x[j] = d_t(1) / d_t(k);}start = std::clock();while (std::clock() - start < CLOCKS_PER_SEC * 2.9) {f(x);if (gequal0) {std::printf("%.20lf\n", lf(A));return 0;}for (ul j = 1; j <= k; ++j) {x[j] += xchange[j];}}std::printf("%.20lf\n", lf(A));return 0;}
注意对于一个可重正整数集,如果其能表示出到,则其能表示出到,且此条件是充要的。于是原题变为次区间查询小于等于指定数的数之和,线段树套树堆即可。不知道为什么会给十五秒的时限。
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul n, q;std::mt19937_64 rnd;class node {public:ul val = 0;ul cnt = 0;ull sum = 0;ul lson = 0;ul rson = 0;ull weight = 0;node() {weight = rnd();}};ul stack[1 << 22];ul remain = 0;ul tot = 0;node tree[1 << 22];void update(ul x){tree[x].sum = tree[x].val * ull(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;}void insert(ul& x, ul v){if (!x) {if (remain) {x = stack[remain];--remain;} else {++tot;x = tot;}tree[x] = node();tree[x].val = v;tree[x].cnt = 1;update(x);return;}if (tree[x].val == v) {++tree[x].cnt;update(x);} else if (tree[x].val < v) {insert(tree[x].rson, v);update(x);if (tree[x].weight < tree[tree[x].rson].weight) {lrotate(x);}} else if (tree[x].val > v) {insert(tree[x].lson, v);update(x);if (tree[x].weight < tree[tree[x].lson].weight) {rrotate(x);}}}void erase(ul& x, ul v){if (tree[x].val == v) {if (tree[x].cnt >= 2) {--tree[x].cnt;update(x);return;}if (!tree[x].lson || !tree[x].rson) {++remain;stack[remain] = x;x = tree[x].lson ^ tree[x].rson;} else if (tree[tree[x].lson].weight > tree[tree[x].rson].weight) {rrotate(x);erase(x, v);} else {lrotate(x);erase(x, v);}} else if (tree[x].val < v) {erase(tree[x].rson, v);update(x);} else if (tree[x].val > v) {erase(tree[x].lson, v);update(x);}}ull getsum(ul x, ull t){if (!x) {return 0;}if (tree[x].val > t) {return getsum(tree[x].lson, t);} else if (tree[x].val == t) {return tree[x].sum - tree[tree[x].rson].sum;} else if (tree[x].val < t) {return tree[x].sum - tree[tree[x].rson].sum + getsum(tree[x].rson, t);}}const ul sz = 1 << 18;ul a[sz];ul heads[sz << 1];void seginsert(ul pos, ul v){for (pos |= sz; pos; pos >>= 1) {insert(heads[pos], v);}}void segerase(ul pos, ul v){for (pos |= sz; pos; pos >>= 1) {erase(heads[pos], v);}}ull getsum(ul l, ul r, ull t){ull ret = 0;for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {if (~l & 1) {ret += getsum(heads[l ^ 1], t);}if (r & 1) {ret += getsum(heads[r ^ 1], t);}}return ret;}int main(){rnd.seed(std::time(0));std::scanf("%u%u", &n, &q);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &a[i]);seginsert(i, a[i]);}for (ul i = 1; i <= q; ++i) {ul qt;std::scanf("%u", &qt);if (qt == 1) {ul x, y;std::scanf("%u%u", &x, &y);segerase(x, a[x]);a[x] = y;seginsert(x, y);} else if (qt == 2) {ul l, r;std::scanf("%u%u", &l, &r);ull t = 1;while (true) {ull newt = getsum(l, r, t) + 1;if (newt == t) {break;}t = newt;}std::printf("%llu\n", t);}}return 0;}
感觉这是个需要很麻烦分类讨论的题,搁置。
参考https://www.zybuluo.com/qq290637843/note/1776933中的情况一。
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul n;ul f(ul x, ul y, ul n){return x + y <= n - 1 ? x + y : x + y - n + 1;}ul g(ul x, ul n){return x + x <= n - 1 ? n - x : n + 1 - x;}const ul maxn = 1000;std::vector<ul> roads[(maxn >> 1) + 1];int main(){std::scanf("%u", &n);if (n & 1) {for (ul i = 1; i <= ((n - 1) >> 1); ++i) {roads[i].push_back(n);roads[i].push_back(f(1, i - 1, n));for (ul j = 1, gj1 = g(1, n); j <= n - 2; ++j, gj1 = g(gj1, n)) {roads[i].push_back(f(gj1, i - 1, n));}roads[i].push_back(n);}for (ul i = 1; i <= n - 1; ++i) {if (i + i <= n - 1) {for (ul j = 0; j <= i; ++j) {if (j) {std::putchar(' ');}std::printf("%u", roads[i][j]);}std::putchar('\n');} else {for (ul j = n - i; j <= n; ++j) {if (j != n - i) {std::putchar(' ');}std::printf("%u", roads[n - i][j]);}std::putchar('\n');}}} else {for (ul i = 1; i <= (n >> 1); ++i) {roads[i].push_back(f(1, i - 1, n + 1));for (ul j = 1, gj1 = g(1, n + 1); j <= n - 1; ++j, gj1 = g(gj1, n + 1)) {roads[i].push_back(f(gj1, i - 1, n + 1));}}for (ul i = 1; i <= n - 1; ++i) {if (i + i <= n - 2) {for (ul j = 0; j <= i; ++j) {if (j) {std::putchar(' ');}std::printf("%u", roads[i][j]);}std::putchar('\n');} else if (i <= n - 2) {for (ul j = n - 1 - i; j <= n - 1; ++j) {if (j != n - 1 - i) {std::putchar(' ');}std::printf("%u", roads[n - 1 - i][j]);}std::putchar('\n');} else {for (ul j = 0; j <= n - 1; ++j) {if (j) {std::putchar(' ');}std::printf("%u", roads[n >> 1][j]);}std::putchar('\n');}}}return 0;}
用表示解决的覆盖问题所需最小花费,那么显然满足如下递推式:
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;using pulll = std::pair<ul, ll>;ul n;const ul maxn = 4e5;ll k;ll x[maxn + 1];ll y[maxn + 1];ll f[maxn + 1];class data1 {public:ul prev = 0;ul next = 0;ll x = 0;ll f = 0;};ul tot = 0;data1 point1[maxn + 1];class edge_t {public:ul to = 0;ul nex = 0;};edge_t edge[maxn + maxn + 1];ul totedge;ul head[maxn + 1];ul rhead[maxn + 1];ul rank[maxn + 1];void addedge(ul a, ul b){++totedge;if (!head[a]) {head[a] = totedge;}edge[totedge].to = b;if (rhead[a]) {edge[rhead[a]].nex = totedge;}rhead[a] = totedge;}ul fa[maxn + 1];std::vector<pulll> stack;void getcen(ul curr, ul prev, ul totsz, ul& sz, ul& mnmxsz, ul& mnmxsznid){sz = 1;ul mxsz = 0;for (ul eid = head[curr]; eid; eid = edge[eid].nex) {ul nex = edge[eid].to;if (rank[nex]) {continue;}if (nex == prev) {continue;}ul sonsz;getcen(nex, curr, totsz, sonsz, mnmxsz, mnmxsznid);mxsz = std::max(mxsz, sonsz);sz += sonsz;}mxsz = std::max(mxsz, totsz - sz);if (mnmxsz > mxsz) {mnmxsz = mxsz;mnmxsznid = curr;}}void getsz(ul curr, ul prev, ul& sz){sz = 1;for (ul eid = head[curr]; eid; eid = edge[eid].nex) {ul nex = edge[eid].to;if (rank[nex]) {continue;}if (nex == prev) {continue;}ul sonsz;getsz(nex, curr, sonsz);sz += sonsz;}}class hull1 {public:ul left = 0;ul right = 0;ul ptr = 0;ll y = 0;void pop_back() {if (ptr == right) {ptr = point1[right].prev;}right = point1[right].prev;point1[right].next = 0;}void pop_front() {if (ptr == left) {ptr = point1[left].next;}left = point1[left].next;point1[left].prev = 0;}};std::vector<hull1> hulls;class data2 {public:ll y = 0;ll fmxy = 0;};data2 point2[maxn + 1];bool check(const data1& a, const data1& b, const data1& c){return (b.f - a.f) * (c.x - b.x) >= (c.f - b.f) * (b.x - a.x);}bool check(const data2& a, const data2& b, const data2& c){return (b.fmxy - a.fmxy) * (c.y - b.y) >= (c.fmxy - b.fmxy) * (b.y - a.y);}void merge(hull1& a, hull1& b){ll y = b.y;while (true) {if (point1[a.right].prev && check(point1[point1[a.right].prev], point1[a.right], point1[b.left])) {a.pop_back();} else if (point1[b.left].next && check(point1[a.right], point1[b.left], point1[point1[b.left].next])) {b.pop_front();} else {break;}}bool flag = b.left == b.ptr;point1[a.right].next = b.left;point1[b.left].prev = a.right;b.left = a.left;if (flag) {b.ptr = a.ptr;while (point1[b.ptr].next && point1[point1[b.ptr].next].f - point1[b.ptr].f < y * (point1[point1[b.ptr].next].x - point1[b.ptr].x)) {b.ptr = point1[b.ptr].next;}}}std::vector<data2> hull2;ul it;void search(ul curr, ul rk){while (it && hull2[it].fmxy - hull2[it - 1].fmxy > (hull2[it].y - hull2[it - 1].y) * (-x[curr] - k)) {--it;}f[curr] = std::min(f[curr], hull2[it].y * (x[curr] + k) + hull2[it].fmxy);for (ul eid = head[curr]; eid; eid = edge[eid].nex) {ul next = edge[eid].to;if (next < curr) {continue;}if (rank[next] > rk) {continue;}search(next, rk);}}int main(){std::scanf("%u%lld", &n, &k);for (ul i = 1; i <= n; ++i) {std::scanf("%lld%lld", &x[i], &y[i]);}stack.push_back(pulll(0, 1e9));for (ul i = 1; i <= n; ++i) {while (stack.back().second <= y[i]) {stack.pop_back();}fa[i] = stack.back().first;stack.push_back(pulll(i, y[i]));addedge(i, fa[i]);addedge(fa[i], i);}for (ul i = 0; i <= n; ++i) {while (!rank[i]) {ul sz;getsz(i, 0, sz);ul mnmxsz = sz, mnmxsznid;getcen(i, -1, sz, sz, mnmxsz, mnmxsznid);rank[mnmxsznid] = sz;}}for (ul i = 1; i <= n; ++i) {f[i] = 3e12;}for (ul i = 1; i <= n; ++i) {hull1 tmp;++tot;tmp.left = tot;tmp.right = tot;tmp.y = y[i];tmp.ptr = tot;point1[tot].x = x[i];point1[tot].f = f[i - 1];while (hulls.size() && hulls.back().y <= y[i]) {merge(hulls.back(), tmp);hulls.pop_back();}hulls.push_back(tmp);point2[i].y = y[i];point2[i].fmxy = point1[tmp.ptr].f - point1[tmp.ptr].x * y[i];hull2.resize(0);for (ul j = i; j && rank[j] <= rank[i]; j = fa[j]) {while (hull2.size() >= 2 && check(hull2[hull2.size() - 2], hull2.back(), point2[j])) {hull2.pop_back();}hull2.push_back(point2[j]);}it = hull2.size() - 1;search(i, rank[i]);}std::printf("%lld\n", f[n]);return 0;}
字典树的后缀自动机
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;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>(1e6);void add(ul c){ul p = las;if (st[p].ch[c]) {las = st[p].ch[c];return;}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;const ul maxn = 3e5;ul n;ul q;char s[maxn + 2];std::vector<ul> sons[maxn + 1];ul las[maxn + 1];std::deque<std::pair<ul, ul>> queue;ul fa[ul(1e6)][20];ul cnt[ul(1e6)];std::vector<ul> sons2[ul(1e6)];ul depth[ul(1e6)];void search(ul curr){for (ul t = 1; (1 << t) <= depth[curr]; ++t) {fa[curr][t] = fa[fa[curr][t - 1]][t - 1];}for (ul next : sons2[curr]) {fa[next][0] = curr;depth[next] = depth[curr] + 1;search(next);cnt[curr] += cnt[next];}}int main(){std::scanf("%u%u", &n, &q);std::scanf("%s", s + 1);for (ul i = 2; i <= n; ++i) {ul f;std::scanf("%u", &f);sons[f].push_back(i);}sam.init();queue.push_back(std::pair<ul, ul>(0, 1));las[0] = 1;while (queue.size()) {auto curr = queue.front();queue.pop_front();sam.las = las[curr.first];sam.add(s[curr.second] - 'A');las[curr.second] = sam.las;curr.first = curr.second;for (ul next : sons[curr.first]) {curr.second = next;queue.push_back(curr);}}for (ul i = 2; i != sam.st.size(); ++i) {sons2[sam.st[i].fa].push_back(i);}for (ul i = 1; i <= n; ++i) {++cnt[las[i]];}search(1);for (ul i = 1; i <= q; ++i) {ul x, l;std::scanf("%u%u", &x, &l);x = las[x];for (ul t = 31 - __builtin_clz(depth[x]); ~t; --t) {if (depth[x] >= (1 << t) && sam.st[fa[x][t]].len >= l) {x = fa[x][t];}}std::printf("%u\n", cnt[x]);}return 0;}
对每个子树求重心。
#pragma GCC target ("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.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;std::vector<ul> edges[maxn + 1];ul sz[maxn + 1];ul cen[maxn + 1];ul fa[maxn + 1];ul type[maxn + 1];void search(ul curr, ul prev){sz[curr] = 1;cen[curr] = curr;for (ul next : edges[curr]) {if (next == prev) {continue;}fa[next] = curr;search(next, curr);if (sz[curr] <= sz[next]) {cen[curr] = cen[next];}sz[curr] += sz[next];while (sz[curr] - sz[cen[curr]] > sz[cen[curr]]) {cen[curr] = fa[cen[curr]];}}if (sz[curr] - sz[cen[curr]] == sz[cen[curr]]) {type[curr] = 2;} else {type[curr] = 1;}}int main(){std::scanf("%u", &n);for (ul i = 1; i <= n - 1; ++i) {ul a, b;std::scanf("%u%u", &a, &b);edges[a].push_back(b);edges[b].push_back(a);}search(1, 0);for (ul i = 1; i <= n; ++i) {if (type[i] == 2) {std::printf("%u %u\n", std::min(cen[i], fa[cen[i]]), std::max(cen[i], fa[cen[i]]));} else {std::printf("%u\n", cen[i]);}}return 0;}