@qq290637843
2020-11-02T06:40:22.000000Z
字数 22039
阅读 280
某种编辑距离。用表示变为的最小花费的有序对(第一个是替换总位数,第二个是替换总次数),那么显然
#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 = 2000, maxm = 4000;ul a[maxn + 1];ul b[maxm + 1];ul T;ul n, q, m;std::stringstream ss;std::string str;std::pair<li, li> operator+(const std::pair<li, li>& a, const std::pair<li, li>& b){return std::pair<li, li>(a.first + b.first, a.second + b.second);}std::pair<li, li> operator-(const std::pair<li, li>& a, const std::pair<li, li>& b){return std::pair<li, li>(a.first - b.first, a.second - b.second);}std::pair<li, li> f[maxn + 1][maxm + 1];std::pair<ul, ul> ffrom[maxn + 1][maxm + 1];std::pair<li, li> g[maxn + 1][maxm + 1];std::pair<ul, ul> gfrom[maxn + 1][maxm + 1];const li inf = 1e9;void initg(ul x, ul y){g[x][y] = std::pair<li, li>(inf + 1, inf + 1);}void updateftog(ul fromx, ul fromy, ul tox, ul toy){if (g[tox][toy] > f[fromx][fromy] - std::pair<li, li>(fromx, 0)) {g[tox][toy] = f[fromx][fromy] - std::pair<li, li>(fromx, 0);gfrom[tox][toy] = std::pair<ul, ul>(fromx, fromy);}}void updategtog(ul fromx, ul fromy, ul tox, ul toy){if (g[tox][toy] > g[fromx][fromy]) {g[tox][toy] = g[fromx][fromy];gfrom[tox][toy] = gfrom[fromx][fromy];}}void initf(ul x, ul y){f[x][y] = std::pair<li, li>(inf + 1, inf + 1);}void updatef(const std::pair<li, li>& v, ul fromx, ul fromy, ul tox, ul toy){if (f[tox][toy] > v) {f[tox][toy] = v;ffrom[tox][toy] = std::pair<ul, ul>(fromx, fromy);}}int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u", &n, &q);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &a[i]);}std::getline(std::cin, str);ul acnt = 0;ul bcnt = 0;for (ul i = 1; i <= q; ++i) {std::getline(std::cin, str);ss.clear();ss.str(str);char ch;ss >> ch;if (ch == 'R') {ul l, r;ss >> l >> r;while (acnt + 1 < l) {++bcnt;++acnt;b[bcnt] = a[acnt];}ul t;while (ss >> t) {++bcnt;b[bcnt] = t;}acnt = r;} else if (ch == 'D') {ul l, r;ss >> l >> r;while (acnt + 1 < l) {++bcnt;++acnt;b[bcnt] = a[acnt];}acnt = r;} else if (ch == 'A') {ul l;ss >> l;while (acnt + 1 < l) {++bcnt;++acnt;b[bcnt] = a[acnt];}ul t;while (ss >> t) {++bcnt;b[bcnt] = t;}}}while (acnt + 1 <= n) {++acnt;++bcnt;b[bcnt] = a[acnt];}m = bcnt;f[0][0] = std::pair<li, li>(0, 0);initg(0, 0);updateftog(0, 0, 0, 0);for (ul y = 1; y <= m; ++y) {f[0][y] = std::pair<li, li>(inf, inf);initg(0, y);updateftog(0, y, 0, y);updategtog(0, y - 1, 0, y);}for (ul x = 1; x <= n; ++x) {f[x][0] = std::pair<li, li>(inf, inf);initg(x, 0);updateftog(x, 0, x, 0);updategtog(x - 1, 0, x, 0);for (ul y = 1; y <= m; ++y) {initf(x, y);updatef(g[x - 1][y - 1] + std::pair<li, li>(x, 1), gfrom[x - 1][y - 1].first, gfrom[x - 1][y - 1].second, x, y);if (a[x] == b[y]) {updatef(f[x - 1][y - 1], x - 1, y - 1, x, y);}initg(x, y);updateftog(x, y, x, y);updategtog(x - 1, y, x, y);updategtog(x, y - 1, x, y);}}std::printf("%d %d\n", f[n][m].first, f[n][m].second);ul x = n, y = m;while (x && y) {if (a[x] == b[y] && ffrom[x][y] == std::pair<ul, ul>(x - 1, y - 1)) {--x;--y;} else {ul px = ffrom[x][y].first;ul py = ffrom[x][y].second;std::printf("%u %u", px + ul(1), x);for (ul i = py + 1; i <= y; ++i) {std::printf(" %u", b[i]);}std::putchar('\n');x = px;y = py;}}}return 0;}
设表示前个新闻能拆出的最大收益。于是显然
#include <bits/stdc++.h>namespace fast_pool {constexpr size_t const size = 481 << 20;unsigned char data[size];unsigned char* ptr = data;void clear() {ptr = data;}void* fast_alloc(size_t n) {ptr += n; return ptr - n;}};template<class T>class myallocator {public:typedef T value_type;typedef value_type* pointer;typedef value_type& reference;typedef value_type const* const_pointer;typedef value_type const& const_reference;typedef size_t size_type;typedef ptrdiff_t difference_type;pointer allocate(size_t n, const T* pHint = 0) {return (pointer)(fast_pool::fast_alloc(n * sizeof(T)));}void deallocate(pointer p, size_type n) {}void destroy(T* p) {p->~T();}void construct(T* p, const T& val) {::new((void *)p) T(val);}size_t max_size() const throw() {return (fast_pool::size + fast_pool::data - fast_pool::ptr) / sizeof(T);}T* address(T& val) const {return &val;}const T* address(const T& val) const {return &val;}myallocator() throw() {}myallocator(const T* p) throw() {}~myallocator() throw() {}template <typename _other> struct rebind { typedef myallocator<_other> other; };};using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul maxn = 1e6;ul T;ul n, l, r;li a[maxn + 1];li s[maxn + 1];li f[maxn + 1];li mns = -li(n);li mxs = li(n);const ul mxsz = 1 << 20;std::list<std::pair<ul, li>, myallocator<std::pair<ul, li>>> tree[mxsz << 1];ul sz;void insert(ul pos, const std::pair<ul, li>& v){for (pos |= sz; pos; pos >>= 1) {while (tree[pos].size() && tree[pos].back().second <= v.second) {tree[pos].pop_back();}tree[pos].push_back(v);}}void erase(ul pos, ul bound){for (pos |= sz; pos; pos >>= 1) {while (tree[pos].size() && tree[pos].front().first < bound) {tree[pos].pop_front();}}}const li inf = 1e9;li query(ul l, ul r){li ret = -inf;for (l = l - 1 | sz, r = r + 1 | sz; l ^ r ^ 1; l >>= 1, r >>= 1) {if (~l & 1) {if (tree[l ^ 1].size()) {ret = std::max(ret, tree[l ^ 1].front().second);}}if (r & 1) {if (tree[r ^ 1].size()) {ret = std::max(ret, tree[r ^ 1].front().second);}}}return ret;}int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u%u", &n, &l, &r);mns = mxs = 0;for (ul i = 1; i <= n; ++i) {std::scanf("%d", &a[i]);s[i] = s[i - 1] + a[i];mns = std::min(mns, s[i]);mxs = std::max(mxs, s[i]);}sz = 1;while (sz < mxs - mns + 1 + 2) {sz <<= 1;}fast_pool::clear();f[0] = 0;for (ul i = 1; i <= n; ++i) {if (i >= r + 1) {erase(s[i - r - 1] - mns + 1, i - r);}if (i >= l) {insert(s[i - l] - mns + 1, std::pair<ul, li>(i - l, f[i - l]));}f[i] = -inf;f[i] = std::max(f[i], query(1, s[i] - 1 - mns + 1) + 1);f[i] = std::max(f[i], query(s[i] - mns + 1, s[i] - mns + 1));f[i] = std::max(f[i], query(s[i] + 1 - mns + 1, mxs - mns + 1) - 1);}for (ul i = n + 1; i <= n - l + r + 1; ++i) {erase(s[i - r - 1] - mns + 1, i - r);}std::printf("%d\n", f[n]);}return 0;}
简单题
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul T;class vec {public:ll x = 0;ll y = 0;};ll operator^(const vec& a, const vec& b){return a.x * b.y - a.y * b.x;}vec a, b, c;int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%lld%lld%lld%lld%lld%lld", &a.x, &a.y, &b.x, &b.y, &c.x, &c.y);std::printf((a ^ b) + (b ^ c) + (c ^ a) > 0 ? "Counterclockwise\n" : "Clockwise\n");}return 0;}
连割树测板题。
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul maxn = 3e5;inline void swap(register ul& a, register ul& b){a ^= b ^= a ^= b;}class link_cut_tree {public:ul c[maxn + 1][1], fa[maxn + 1], top, q[maxn + 1], rev[maxn + 1];inline void pushdown(register ul x) {if (rev[x]) {register ul l = c[x][0], r = c[x][2];rev[l] ^= 1, rev[r] ^= 1, rev[x] ^= 1;swap(c[x][0], c[x][3]);}}inline bool isroot(register ul x) {return c[fa[x]][0] != x && c[fa[x]][4] != x;}inline void rotate(register 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;}fa[x] = z;fa[y] = x;fa[c[x][r]] = y;c[y][l] = c[x][r];c[x][r] = y;}inline void splay(register ul x) {top = 1;q[top] = x;for (register ul i = x; !isroot(i); i = fa[i]) {q[++top] = fa[i];}for (register 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(register ul x) {for (register ul t = 0; x; t = x, x = fa[x]) {splay(x);c[x][5] = t;}}inline void evert(register ul x) {access(x);splay(x);rev[x] ^= 1;}inline ul root(register ul x) {access(x);splay(x);while (c[x][0]) {x = c[x][0];}return x;}inline void split(register ul x, register ul y) {evert(x);access(y);splay(y);}inline void cut(register ul x, register ul y) {split(x, y);if (c[y][0] == x) {c[y][0] = 0;fa[x] = 0;}}inline void link(register ul x, register ul y) {evert(x);fa[x] = y;}};link_cut_tree tree;ul T;ul n, m, q;const ul maxm = 3e5;ul u[maxm + 1];ul v[maxm + 1];ul big[maxm + 1];int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u%u", &n, &m, &q);for (ul i = 1; i <= m; ++i) {std::scanf("%u%u", &u[i], &v[i]);}for (ul l = 1, r = 0; l <= m; ++l) {while (r + 1 <= m && tree.root(u[r + 1]) != tree.root(v[r + 1])) {++r;tree.link(u[r], v[r]);}big[l] = r;tree.cut(u[l], v[l]);}ul ans = 0;for (ul i = 1; i <= q; ++i) {ul l, r;std::scanf("%u%u", &l, &r);ul k1 = (l ^ ans) % m + 1;ul k2 = (r ^ ans) % m + 1;l = std::min(k1, k2);r = std::max(k1, k2);ans = r > big[l];std::printf(ans ? "Yes\n" : "No\n");}}return 0;}
搁置
简单题
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul T;const ul maxn = 1e5;ul n;li k;li l, r;li mn[maxn + 1];li mx[maxn + 1];li ans[maxn + 1];int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%d", &n, &k);std::scanf("%d%d", &mn[1], &mx[1]);bool flag = true;for (ul i = 2; i <= n; ++i) {std::scanf("%d%d", &l, &r);mx[i] = std::min(mx[i - 1] + k, r);mn[i] = std::max(mn[i - 1] - k, l);if (mn[i] > mx[i]) {flag = false;}}if (!flag) {std::printf("NO\n");continue;}ans[n] = mn[n];for (ul i = n - 1; i >= 1; --i) {mx[i] = std::min(ans[i + 1] + k, mx[i]);mn[i] = std::max(ans[i + 1] - k, mn[i]);ans[i] = mn[i];}std::printf("YES\n");for (ul i = 1; i <= n; ++i) {if (i != 1) {std::putchar(' ');}std::printf("%d", ans[i]);}std::putchar('\n');}return 0;}
只说明互质的情况。
题面好像有点问题,如果完全安题面的意思,那个拿走一张牌造成互质的人应该是赢家才对,但是按照样例解释,就成了“造成互质”是违法操作了。或者准确说,题面中并没有定义“违法操作”。
设,那么答案显然为,直接动态规划即可。
#pragma GCC target("pclmul")#include <bits/stdc++.h>#include <emmintrin.h>#include <wmmintrin.h>namespace fast_pool {constexpr size_t const size = 481 << 20;unsigned char data[size];unsigned char* ptr = data;void clear() {ptr = data;}void* fast_alloc(size_t n) {ptr += n; return ptr - n;}};template<class T>class myallocator {public:typedef T value_type;typedef value_type* pointer;typedef value_type& reference;typedef value_type const* const_pointer;typedef value_type const& const_reference;typedef size_t size_type;typedef ptrdiff_t difference_type;pointer allocate(size_t n, const T* pHint = 0) {return (pointer)(fast_pool::fast_alloc(n * sizeof(T)));}void deallocate(pointer p, size_type n) {}void destroy(T* p) {p->~T();}void construct(T* p, const T& val) {::new((void *)p) T(val);}size_t max_size() const throw() {return (fast_pool::size + fast_pool::data - fast_pool::ptr) / sizeof(T);}T* address(T& val) const {return &val;}const T* address(const T& val) const {return &val;}myallocator() throw() {}myallocator(const T* p) throw() {}~myallocator() throw() {}template <typename _other> struct rebind { typedef myallocator<_other> other; };};using us = std::uint16_t;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;using lll = __int128_t;using ulll = __uint128_t;ul T;ul n;const ul maxn = 100;class counter {public:ul g = 0;ul sz = 0;ulll cnt = 0;counter()=default;counter(ul a, ul b, ulll c): g(a), sz(b), cnt(c) {};};std::vector<counter, myallocator<counter>> curr;std::vector<counter, myallocator<counter>> next;llf lnfac[maxn + 1];ul a[maxn + 1];ulll cnt[maxn + 1];const ul maxa = 1e5;const ul bound = 2154;ul small[maxa + 1];ul low[maxa + 1];ul num[maxa + 1][6];ul algcd[bound + 1][bound + 1];inline ul sp(ul a1, ul a2, ul b){static ul t;return t = algcd[a1][b % a1], b /= t, (a2 <= bound ? algcd[a2][b % a2] : (b % a2 ? ul(1) : a2)) * t;}inline ul gcd(ul a, ul b){return (a && b) ? (a <= bound ? (b <= bound ? algcd[a][b] : algcd[a][b % a]) : (b <= bound ? algcd[a % b][b] : sp(num[a][0], num[a][7], b))) : (a ^ b);}std::mt19937 rnd;char outstr[100000];char* outend = outstr;int main(){rnd.seed(std::time(0));for (ul i = 1; i <= maxa; ++i) {small[i] = 1;}num[1][0] = num[1][8] = 1;for (ul i = 1; i <= maxa; ++i) {if (small[i] == 1) {for (ul j = i; j <= maxa; j += i) {small[j] *= i;if (small[j] == i) {low[j] = i;}}}if (i >= 2) {std::memcpy(num[i], num[i / low[i]], sizeof(ul) * 2);num[i][0] *= low[i];if (num[i][0] > num[i][9]) {std::swap(num[i][0], num[i][10]);}}}for (ul i = 0; i <= bound; ++i) {algcd[i][0] = i;algcd[0][i] = i;}for (ul i = 1; i <= bound; ++i) {for (ul j = 1; j <= bound; ++j) {ul x = i, y = j;while (!algcd[x][y]) {y ^= x ^= y ^= x %= y;}algcd[i][j] = algcd[x][y];}}lnfac[0] = 0;for (ul i = 1; i <= maxn; ++i) {lnfac[i] = lnfac[i - 1] + std::log(llf(i));}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);for (ul i = 1; i <= n; ++i) {cnt[i] = 0;}ul g = 0;for (ul i = 1; i <= n; ++i) {std::scanf("%u", &a[i]);a[i] = small[a[i]];g = gcd(g, a[i]);}if (g != 1) {std::sprintf(outend, (n & 1) ? "1.0000\n" : "0.0000\n");outend += std::strlen(outend);continue;}for (ul i = n; i >= 1; --i) {std::swap(a[i], a[rnd() % i + 1]);}curr.resize(0);curr.push_back(counter(0, 0, 1));for (ul i = 1; i <= n; ++i) {next.resize(0);for (const auto& t : curr) {next.push_back(t);ul ng = gcd(t.g, a[i]);if (ng != 1) {next.push_back(counter(ng, t.sz + 1, t.cnt));}}std::sort(next.begin(), next.end(), [](const counter& a, const counter& b){return a.g != b.g ? a.g < b.g : a.sz < b.sz;});curr.resize(0);for (const auto& t : next) {if (curr.empty() || curr.back().g != t.g || curr.back().sz != t.sz) {curr.push_back(t);} else {curr.back().cnt += t.cnt;}}}for (ul key = 1; key <= n; ++key) {for (const auto& t : curr) {if (~t.sz & 1) {continue;}if (gcd(t.g, a[key]) == 1) {cnt[t.sz + 1] += t.cnt;}}}llf ans = 0;for (ul k = 2; k <= n; k += 2) {ans += std::exp(std::log(llf(cnt[k])) + lnfac[k - 1] + lnfac[n - k] - lnfac[n]);}std::sprintf(outend, "%.9lf\n", lf(ans));outend += std::strlen(outend);}std::printf(outstr);return 0;}
做法和官方题解一致。

#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul T, n;void f(ul x, char c1, char c2){for (ul i = 1; i <= x; ++i) {std::putchar(c1);std::putchar(c2);}}void rot(char &ch){--ch;if (ch < '1') {ch = '6';}}int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);if (n & 1) {for (ul i = 3; i <= n; i += 2) {std::putchar('1');for (char ch1 = '6', ch2 = '4', ch3 = '5', ch4 = '3'; ; rot(ch1), rot(ch2), rot(ch3), rot(ch4)) {f(i - 3, ch1, ch2);std::putchar(ch1);std::putchar(ch3);if (ch1 == '1') {break;}std::putchar(ch4);}}} else {std::printf("643216");for (ul i = 4; i <= n; i += 2) {std::putchar('1');for (char ch1 = '6', ch2 = '4', ch3 = '5', ch4 = '3'; ; rot(ch1), rot(ch2), rot(ch3), rot(ch4)) {f(i - 3, ch1, ch2);std::putchar(ch1);std::putchar(ch3);if (ch1 == '1') {break;}std::putchar(ch4);}}}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;std::mt19937 rnd;ul base;inline ul mul(ul a, ul b) {auto vc = _mm_clmulepi64_si128(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b), 0);auto vf = _mm_xor_si128(vc, _mm_clmulepi64_si128(_mm_srli_epi64(vc, 32), _mm_set_epi32(0, 0, 1, 141), 0));return _mm_cvtsi128_si32(_mm_xor_si128(vf, _mm_clmulepi64_si128(_mm_srli_epi64(vf, 32), _mm_set_epi32(0, 0, 1, 141), 0)));}const ul maxn = 5e6;ul hash[maxn + 1];char str[maxn + 2];ul basepow[maxn + 1];ul n, T;ul gethash(ul a, ul b){return hash[b] ^ mul(hash[a - 1], basepow[b - a + 1]);}const ul sz = 1 << 26;const ul mask = sz - 1;ul tim;ul ex[sz];int main(){rnd.seed(std::time(0));base = rnd();basepow[0] = 1;for (ul i = 1; i <= maxn; ++i) {basepow[i] = mul(base, basepow[i - 1]);}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);std::scanf("%s", str + 1);for (ul i = 1; i <= n; ++i) {hash[i] = mul(hash[i - 1], base) ^ str[i];}bool flag1 = false;for (ul k = 2; k <= n; ++k) {if (n % k != 0) {continue;}ul len = n / k;bool flag2 = true;++tim;for (ul i = 1; i <= len; ++i) {ex[(hash[i] ^ mul(hash[len], basepow[i]) ^ mul(hash[i], basepow[len])) & mask] = tim;;}for (ul s = len + 1, t = s + len - 1; s <= n; s += len, t += len) {if (ex[gethash(s, t) & mask] != tim) {flag2 = false;break;}}if (flag2) {flag1 = true;break;}}std::printf(flag1 ? "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;namespace fast_pool {constexpr size_t const size = 481 << 20;unsigned char data[size];unsigned char* ptr = data;void clear() {ptr = data;}void* fast_alloc(size_t n) {ptr += n; return ptr - n;}};template<class T>class myallocator {public:typedef T value_type;typedef value_type* pointer;typedef value_type& reference;typedef value_type const* const_pointer;typedef value_type const& const_reference;typedef size_t size_type;typedef ptrdiff_t difference_type;pointer allocate(size_t n, const T* pHint = 0) {return (pointer)(fast_pool::fast_alloc(n * sizeof(T)));}void deallocate(pointer p, size_type n) {}void destroy(T* p) {p->~T();}void construct(T* p, const T& val) {::new((void *)p) T(val);}size_t max_size() const throw() {return (fast_pool::size + fast_pool::data - fast_pool::ptr) / sizeof(T);}T* address(T& val) const {return &val;}const T* address(const T& val) const {return &val;}myallocator() throw() {}myallocator(const T* p) throw() {}~myallocator() throw() {}template <typename _other> struct rebind { typedef myallocator<_other> other; };};const ul mod = 998244353;ul plus(ul a, ul b){return a + b < mod ? a + b : a + b - mod;}ul minus(ul a, ul b){return a < b ? a + mod - b : a - b;}ul mul(ul a, ul b){return ull(a) * ull(b) % mod;}void exgcd(li a, li b, li& x, li& y){if (b) {exgcd(b, a % b, y, x);y -= a / b * x;} else {x = 1;y = 0;}}ul inverse(ul a){li x, y;exgcd(a, mod, x, y);return x < 0 ? x + li(mod) : x;}ul T;const ul maxn = 5e3;ul n, m, e;ul fac[maxn + 1];ul fiv[maxn + 1];ul inv[maxn + 1];std::vector<ul> edge[maxn + 1];std::vector<ul> fa[maxn + 1];std::list<ul, myallocator<ul>> queue;ul dis[maxn + 1];ul al[maxn + 1];ul altim;ul s[maxn + 1];const ul inf = ~ul(0);ul a[maxn + 1], b[maxn + 1];ul f[maxn + 1][maxn + 1];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]);}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u%u", &n, &m, &e);for (ul i = 1; i <= n; ++i) {edge[i].resize(0);fa[i].resize(0);dis[i] = inf;}for (ul i = 1; i <= m; ++i) {ul u, v;std::scanf("%u%u", &u, &v);edge[u].push_back(v);edge[v].push_back(u);}dis[e] = 0;fast_pool::clear();queue.clear();queue.push_back(e);while (queue.size()) {ul curr = queue.front();queue.pop_front();for (ul next : edge[curr]) {if (dis[next] > dis[curr]) {fa[next].push_back(curr);}if (dis[next] != inf) {continue;}queue.push_back(next);dis[next] = dis[curr] + 1;}}for (ul i = 1; i <= n; ++i) {s[i] = 0;++altim;al[i] = altim;++s[i];fast_pool::clear();queue.clear();queue.push_back(i);while (queue.size()) {ul curr = queue.front();queue.pop_front();for (ul next : edge[curr]) {if (dis[next] != dis[curr] + 1 || al[next] == altim) {continue;}al[next] = altim;++s[i];queue.push_back(next);}}}ul ans = fac[n];++altim;for (ul i = 1; i <= n; ++i) {if (i == e) {continue;}ul x = fa[i].front();ul y = fa[i].back();a[0] = b[0] = i;ul cnt = 0;while (x != y) {++cnt;a[cnt] = x;b[cnt] = y;al[x] = altim;al[y] = altim;x = fa[x].front();y = fa[y].front();}if (!cnt) {continue;}f[0][0] = 1;for (ul y = 1; y <= cnt; ++y) {f[0][y] = mul(inv[s[b[y]]], f[0][y - 1]);}for (ul x = 1; x <= cnt; ++x) {f[x][0] = mul(inv[s[a[x]]], f[x - 1][0]);for (ul y = 1; y <= cnt; ++y) {f[x][y] = mul(inv[s[a[x]] + s[b[y]] - s[i]], plus(f[x - 1][y], f[x][y - 1]));}}ans = mul(ans, f[cnt][cnt]);}for (ul i = 1; i <= n; ++i) {if (altim != al[i]) {ans = mul(ans, inv[s[i]]);}}std::printf("%u\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;inline ul mul(ul a, ul b) {auto vc = _mm_clmulepi64_si128(_mm_cvtsi32_si128(a), _mm_cvtsi32_si128(b), 0);auto vf = _mm_xor_si128(vc, _mm_clmulepi64_si128(_mm_srli_epi64(vc, 32), _mm_set_epi32(0, 0, 1, 141), 0));return _mm_cvtsi128_si32(_mm_xor_si128(vf, _mm_clmulepi64_si128(_mm_srli_epi64(vf, 32), _mm_set_epi32(0, 0, 1, 141), 0)));}ul T;const ul maxn = 2e5;const ul maxm = 5e4;ul n, m, k;std::vector<ul> base;ul wash(ul x){for (ul t : base) {x = std::min(x, x ^ t);}return x;}ul a[maxn + 1];ul b[maxm + 1];ul hasha[maxn + 1];ul hashb;std::mt19937 rnd;ul basepow[maxn + 1];const ul mod = 1e9 + 7;ul plus(ul a, ul b){return a + b < mod ? a + b : a + b - mod;}ul twopow[maxn + 1];ul gethash(ul l, ul r){return hasha[r] ^ mul(hasha[l - 1], basepow[r - l + 1]);}int main(){twopow[0] = 1;for (ul i = 1; i <= maxn; ++i) {twopow[i] = plus(twopow[i - 1], twopow[i - 1]);}rnd.seed(std::time(0));const ul hashbase = rnd();basepow[0] = 1;for (ul i = 1; i <= maxn; ++i) {basepow[i] = mul(basepow[i - 1], hashbase);}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u%u", &n, &m, &k);for (ul i = 1; i <= n; ++i) {std::scanf("%u", &a[i]);}for (ul i = 1; i <= m; ++i) {std::scanf("%u", &b[i]);}base.resize(0);for (ul i = 1; i <= k; ++i) {ul s;std::scanf("%u", &s);s = wash(s);if (s) {base.push_back(s);}}hashb = 0;for (ul i = 1; i <= m; ++i) {hashb = mul(hashb, hashbase) ^ wash(b[i]);}for (ul i = 1; i <= n; ++i) {hasha[i] = mul(hasha[i - 1], hashbase) ^ wash(a[i]);}ul ans = 0;for (ul i = 1, j = m; j <= n; ++i, ++j) {if (gethash(i, j) == hashb) {ans = plus(ans, twopow[i - 1]);}}std::printf("%u\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;const ul maxn = 2e3;ul T;ul n;std::vector<ul> edge[maxn + 1];li l[maxn + 1], r[maxn + 1];using seg_t = std::pair<li, li>;using node_t = std::pair<seg_t, ul>;std::vector<node_t> f[maxn + 1];std::vector<node_t> tmp1;std::vector<node_t> tmp2;const li inf = 1e9 + 1;void search(ul curr, ul prev){for (ul next : edge[curr]) {if (next == prev) {continue;}search(next, curr);}tmp1.resize(0);tmp1.push_back(node_t(seg_t(-inf, l[curr] - 1), inf));tmp1.push_back(node_t(seg_t(l[curr], r[curr]), 0));tmp1.push_back(node_t(seg_t(r[curr] + 1, inf), inf));for (ul next : edge[curr]) {if (next == prev) {continue;}tmp2.resize(0);for (auto it1 = tmp1.begin(), it2 = f[next].begin(); it1 != tmp1.end() && it2 != f[next].end(); ) {li l = std::max(it1->first.first, it2->first.first);li r = std::min(it1->first.second, it2->first.second);tmp2.push_back(node_t(seg_t(l, r), it1->second + it2->second));if (it1->first.second < it2->first.second) {++it1;} else if (it2->first.second < it1->first.second) {++it2;} else {++it1;++it2;}}tmp1.resize(0);for (const auto& t : tmp2) {if (tmp1.empty() || tmp1.back().second != t.second) {tmp1.push_back(t);} else {tmp1.back().first.second = t.first.second;}}}ul mn = inf;for (const auto& t : tmp1) {mn = std::min(mn, t.second);}f[curr].resize(0);for (const auto& t : tmp1) {if (t.second == mn) {f[curr].push_back(t);} else {f[curr].push_back(node_t(t.first, mn + 1));}}}int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);for (ul i = 1; i <= n; ++i) {edge[i].resize(0);}for (ul i = 1; i <= n - 1; ++i) {ul u, v;std::scanf("%u%u", &u, &v);edge[u].push_back(v);edge[v].push_back(u);}for (ul i = 1; i <= n; ++i) {std::scanf("%d%d", &l[i], &r[i]);}search(1, 0);for (const auto& t : f[1]) {if (t.first.first <= 0 && t.first.second >= 0) {std::printf("%u\n", t.second);}}}return 0;}