@qq290637843
2021-01-30T13:19:08.000000Z
字数 25524
阅读 501
题目见https://www.jisuanke.com/contest/5528/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;ul n;int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u", &n);std::printf("%u\n", (n + 1 >> 1) + 1);}return 0;}
倒着考虑,就是说每走一步挖掉一个格子,要求任何时刻剩余的格子构成的区域是满足要求的。那么显然,一开始只能选择从四角挖,接着,只能沿着剩余区域的一边走,不到端点不能转弯,于是乎任何时候都是从剩余区域挖掉一条边然后留下一个长方形。一开始的选角数量等于,接下来就是简单的选次作为删横边,次作为删竖边。
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;const ul mod = 1e9 + 7;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;ul n, m;const ul maxn = 1e6;const ul maxm = 1e6;ul fac[maxn + maxm + 1];ul fiv[maxn + maxm + 1];int main(){fac[0] = 1;for (ul i = 1; i <= maxn + maxm; ++i) {fac[i] = mul(fac[i - 1], i);}fiv[maxn + maxm] = inverse(fac[maxn + maxm]);for (ul i = maxn + maxm; i >= 1; --i) {fiv[i - 1] = mul(fiv[i], i);}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u", &n, &m);std::printf("%u\n", mul(mul((n >= 2) + 1, (m >= 2) + 1), mul(fac[n + m - 2], mul(fiv[n - 1], fiv[m - 1]))));}return 0;}
简单动态规划
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;using pulul = std::pair<ul, ul>;using plipulul = std::pair<li, pulul>;const ul mod = 1e9 + 7;ul plus(ul a, ul b){return a + b < mod ? a + b : a + b - mod;}ul n, m;const ul maxn = 1000;const ul maxm = 1000;ul ans[maxn + 1][maxm + 1][5];ul out = 0;li val[maxn + 2][maxm + 2];std::vector<plipulul> pos;int main(){std::scanf("%u%u", &n, &m);for (ul j = 1; j <= m; ++j) {val[0][j] = val[n + 1][j] = 1e9;}for (ul i = 1; i <= n; ++i) {val[i][0] = val[i][m + 1] = 1e9;}for (ul i = 1; i <= n; ++i) {for (ul j = 1; j <= m; ++j) {std::scanf("%d", &val[i][j]);pos.push_back(plipulul(val[i][j], pulul(i, j)));}}std::sort(pos.begin(), pos.end());for (const auto& p : pos) {const auto& curr = p.second;bool ishead = true;bool istail = true;for (const auto& prev : {pulul(curr.first + 1, curr.second), pulul(curr.first, curr.second + 1), pulul(curr.first - 1, curr.second), pulul(curr.first, curr.second - 1)}) {if (val[prev.first][prev.second] == p.first - 1) {ishead = false;for (ul i = 1; i <= 4; ++i) {ans[curr.first][curr.second][std::min(i + 1, ul(4))] = plus(ans[curr.first][curr.second][std::min(i + 1, ul(4))], ans[prev.first][prev.second][i]);}}if (val[prev.first][prev.second] == p.first + 1) {istail = false;}}if (ishead) {ans[curr.first][curr.second][1] = 1;}if (istail) {out = plus(out, ans[curr.first][curr.second][4]);}}std::printf("%u\n", out);return 0;}
首先将所有洞的出边全部砍掉。
于是实际就是要对每一个求,考虑分母和分子该怎么求。
由于
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;using pulul = std::pair<ul, ul>;pulul operator+(const pulul& a, const pulul& b){return pulul(a.first + b.first, a.second + b.second);}const ul mod = 1e9 + 7;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;ul n;ul k;ul tot;const ul maxn = 200;const ul maxk = 200;const ul maxtot = maxk + maxn;bool ishole[maxn + 1][maxn + 2];pulul holes[maxk + 1];pulul from[maxk + maxn + 1];ul fromid[maxn + 1][maxn + 2];class val_t {public:ul dx[maxtot + 1];ul dy[maxtot + 1];ul c;void init(){std::memset(dx + 1, 0, sizeof(ul) * tot);std::memset(dy + 1, 0, sizeof(ul) * tot);c = 0;}};val_t operator+(const val_t& a, const val_t& b){static val_t ret;for (ul i = 1; i <= tot; ++i) {ret.dx[i] = plus(a.dx[i], b.dx[i]);}for (ul i = 1; i <= tot; ++i) {ret.dy[i] = plus(a.dy[i], b.dy[i]);}ret.c = plus(a.c, b.c);return ret;}val_t operator-(const val_t& a, const val_t& b){static val_t ret;for (ul i = 1; i <= tot; ++i) {ret.dx[i] = minus(a.dx[i], b.dx[i]);}for (ul i = 1; i <= tot; ++i) {ret.dy[i] = minus(a.dy[i], b.dy[i]);}ret.c = minus(a.c, b.c);return ret;}val_t operator*(const val_t& a, ul b){static val_t ret;for (ul i = 1; i <= tot; ++i) {ret.dx[i] = mul(a.dx[i], b);}for (ul i = 1; i <= tot; ++i) {ret.dy[i] = mul(a.dy[i], b);}ret.c = mul(a.c, b);return ret;}val_t operator/(const val_t& a, ul b){return a * inverse(b);}ul deg[maxn + 1][maxn + 2];template<typename T>T& at(T v[][maxn + 2], const pulul& p){return v[p.first][p.second];}val_t ans[maxn + 1][maxn + 2][2];pulul s;ul a[maxtot + 1][maxtot + 1];ul b[maxtot + 1];void solve(ul a[][maxtot + 1], ul b[], ul x[]){for (ul i = 1; i <= tot; ++i) {if (!a[i][i]) {for (ul j = i + 1; j <= tot; ++j) {if (a[j][i]) {for (ul k = i; k <= tot; ++k) {std::swap(a[i][k], a[j][k]);}std::swap(b[i], b[j]);break;}}}ul t = inverse(a[i][i]);for (ul j = i; j <= tot; ++j) {a[i][j] = mul(a[i][j], t);}b[i] = mul(b[i], t);for (ul j = 1; j <= tot; ++j) {if (j == i) {continue;}t = a[j][i];if (t) {for (ul k = i; k <= tot; ++k) {a[j][k] = minus(a[j][k], mul(t, a[i][k]));}b[j] = minus(b[j], mul(t, b[i]));}}}std::memcpy(x + 1, b + 1, sizeof(ul) * tot);}ul x[maxtot + 1];ul y[maxtot + 1];int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%u%u", &n, &k);for (ul i = 0; i <= n; ++i) {std::memset(ishole[i], false, sizeof(bool) * (n + 2));}deg[1][1] = 2;for (ul j = 2; j <= n - 1; ++j) {deg[1][j] = 3;}deg[1][n] = 2;for (ul i = 2; i <= n - 1; ++i) {deg[i][1] = 3;for (ul j = 2; j <= n - 1; ++j) {deg[i][j] = 4;}deg[i][n] = 3;}deg[n][1] = 2;for (ul j = 2; j <= n - 1; ++j) {deg[n][j] = 3;}deg[n][n] = 2;for (ul i = 1; i <= k; ++i) {std::scanf("%u%u", &holes[i].first, &holes[i].second);at(ishole, holes[i]) = true;}std::scanf("%u%u", &s.first, &s.second);for (ul i = 1; i <= k; ++i) {at(fromid, holes[i]) = i;from[i] = holes[i];}tot = k;for (ul j = 1; j <= n; ++j) {if (!ishole[1][j]) {++tot;fromid[1][j] = tot;from[tot] = pulul(1, j);}}for (ul i = 1; i <= tot; ++i) {at(ans, from[i])[0].init();at(ans, from[i])[1].init();at(ans, from[i])[0].dx[i] = 1;at(ans, from[i])[1].dy[i] = 1;}for (pulul curr(2, 1); curr.first <= n; ++curr.first) {for (curr.second = 1; curr.second <= n; ++curr.second) {if (at(ishole, curr)) {continue;}pulul up = curr + pulul(-1, 0);at(ans, curr)[0] = at(ans, up)[0];at(ans, curr)[1] = at(ans, up)[1] - at(ans, up)[0];for (const auto& next : {up + pulul(0, 1), up + pulul(-1, 0), up + pulul(0, -1)}) {if (next.first < 1 || next.second < 1 || next.second > n) {continue;}if (at(ishole, next)) {continue;}at(ans, curr)[0] = at(ans, curr)[0] - at(ans, next)[0] / at(deg, next);at(ans, curr)[1] = at(ans, curr)[1] - at(ans, next)[1] / at(deg, next);if (next == s) {at(ans, curr)[0].c = minus(at(ans, curr)[0].c, inverse(at(deg, s)));}}if (curr == s) {at(ans, curr)[0].c = minus(at(ans, curr)[0].c, inverse(at(deg, s)));}at(ans, curr)[0] = at(ans, curr)[0] * at(deg, curr);at(ans, curr)[1] = at(ans, curr)[1] * at(deg, curr);}}ul eqtot = 0;for (pulul curr(1, 1); curr.first <= n; ++curr.first) {for (curr.second = 1; curr.second <= n; ++curr.second) {if (curr.first == n || at(ishole, curr + pulul(1, 0))) {++eqtot;val_t tmp = at(ans, curr)[0];for (const auto& next : {curr + pulul(0, 1), curr + pulul(-1, 0), curr + pulul(0, -1)}) {if (next.first < 1 || next.second < 1 || next.second > n) {continue;}if (at(ishole, next)) {continue;}tmp = tmp - at(ans, next)[0] / at(deg, next);if (next == s) {tmp.c = minus(tmp.c, inverse(at(deg, s)));}}std::memcpy(a[eqtot] + 1, tmp.dx + 1, sizeof(ul) * tot);b[eqtot] = minus(0, tmp.c);}}}solve(a, b, x);eqtot = 0;for (pulul curr(1, 1); curr.first <= n; ++curr.first) {for (curr.second = 1; curr.second <= n; ++curr.second) {if (curr.first == n || at(ishole, curr + pulul(1, 0))) {++eqtot;val_t tmp = at(ans, curr)[1] - at(ans, curr)[0];for (const auto& next : {curr + pulul(0, 1), curr + pulul(-1, 0), curr + pulul(0, -1)}) {if (next.first < 1 || next.second < 1 || next.second > n) {continue;}if (at(ishole, next)) {continue;}tmp = tmp - at(ans, next)[1] / at(deg, next);}std::memcpy(a[eqtot] + 1, tmp.dy + 1, sizeof(ul) * tot);b[eqtot] = minus(0, tmp.c);for (ul i = 1; i <= tot; ++i) {b[eqtot] = minus(b[eqtot], mul(x[i], tmp.dx[i]));}}}}solve(a, b, y);for (ul i = 1; i <= k; ++i) {if (i != 1) {std::putchar(' ');}if (!x[i]) {std::printf("GG");} else {std::printf("%u", mul(y[i], inverse(x[i])));}}std::putchar('\n');}return 0;}
在正整数上是一个积性函数,证明见https://projecteuclid.org/download/pdf_1/euclid.bams/1183503695。
#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 sp = 3162277;std::vector<ul> prime;std::vector<bool> notprime(sp + 1, false);ul T;const ul maxn = 1e6;ull f[maxn + 1];ull remain[maxn + 1];ull l, r, k, p;int main(){for (ul i = 2; i <= sp; ++i) {if (!notprime[i]) {prime.push_back(i);}for (ul p : prime) {if (p * i > sp) {break;}notprime[p * i] = true;if (i % p == 0) {break;}}}std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%llu%llu%llu%llu", &l, &r, &k, &p);ull ans = 0;if (l == 0) {++l;ans = (1 ^ k) % p;}for (ull i = l; i <= r; ++i) {f[i - l + 1] = 6;remain[i - l + 1] = i;}for (ull p : prime) {if (p * p > r) {break;}for (ull t = (l + p - 1) / p * p; t <= r; t += p) {ull tmp = 1;while (remain[t - l + 1] % p == 0) {remain[t - l + 1] /= p;tmp *= p;}if (p == 2) {continue;}if (p & 2) {f[t - l + 1] *= tmp + 2 * (tmp - 1) / (p - 1);} else {f[t - l + 1] *= tmp;}}}for (ull i = l; i <= r; ++i) {if (remain[i - l + 1] != 1) {if (remain[i - l + 1] == 2) {} else if (remain[i - l + 1] & 2) {f[i - l + 1] *= remain[i - l + 1] + 2;} else {f[i - l + 1] *= remain[i - l + 1];}}ans = (ans + (f[i - l + 1] ^ k)) % p;}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;ul n, m;const ul maxn = 2e5;const ul maxm = 2e5;const ul maxlen = 2e5;char str[maxlen + 2];class node {public:ul ch[26];node() {std::memset(ch, 0, sizeof(ch));}};ul tot = 1;node tree[maxlen + 2];ul ptt[maxn + 1];ul dfn[maxlen + 2];ul bdfn[maxlen + 2];ul tim = 0;void search(ul curr) {++tim;dfn[curr] = tim;for (ul i = 0; i != 26; ++i) {if (tree[curr].ch[i]) {search(tree[curr].ch[i]);}}bdfn[curr] = tim;}class data {public:bool insert = false;ul val = 0;ul time = 0;ul pos = 0;ul dfn = 0;};ul ans[maxm + 1];data v[maxn + maxm * 4 + 1];ul stack1[maxn + maxm * 4 + 1];ul stack2[maxn + maxm * 4 + 1];ul stack3[maxn + maxm * 4 + 1];void solve3(ul l, ul r){if (v[stack3[l]].dfn == v[stack3[r]].dfn) {return;}ul tmp = 0;for (ul i = l, j = i; i <= r; i = j) {for (j = i; j <= r && v[stack3[j]].dfn == v[stack3[i]].dfn; ++j) {if (!v[stack3[j]].insert) {ans[v[stack3[j]].time] += v[stack3[j]].val * tmp;}}for (j = i; j <= r && v[stack3[j]].dfn == v[stack3[i]].dfn; ++j) {if (v[stack3[j]].insert) {tmp += v[stack3[j]].val;}}}}void solve2(ul l, ul r){if (v[stack2[l]].pos == v[stack2[r]].pos) {return;}ul midl, midr;if ((l ^ r) & 1) {midl = l + r >> 1;midr = midl + 1;} else {midl = l + r >> 1;midr = midl;}ul s = v[stack2[midl]].pos;ul t = v[stack2[midr]].pos;if (s == t) {while (v[stack2[midl]].pos == s && v[stack2[midr]].pos == t) {--midl;++midr;}if (v[stack2[midl]].pos != s) {midr = midl + 1;} else {midl = midr - 1;}}solve2(l, midl);solve2(midr, r);ul tot = 0;bool flag = false;for (ul i = l; i <= midl; ++i) {if (v[stack2[i]].insert) {++tot;stack3[tot] = stack2[i];flag = true;}}if (!flag) {return;}flag = false;for (ul i = midr; i <= r; ++i) {if (!v[stack2[i]].insert) {++tot;stack3[tot] = stack2[i];flag = true;}}if (!flag) {return;}std::sort(stack3 + 1, stack3 + tot + 1, [](ul a, ul b){return v[a].dfn < v[b].dfn;});solve3(1, tot);}void solve1(ul l, ul r){if (v[stack1[l]].time == v[stack1[r]].time) {return;}ul midl, midr;if ((l ^ r) & 1) {midl = l + r >> 1;midr = midl + 1;} else {midl = l + r >> 1;midr = midl;}ul s = v[stack1[midl]].time;ul t = v[stack1[midr]].time;if (s == t) {while (v[stack1[midl]].time == s && v[stack1[midr]].time == t) {--midl;++midr;}if (v[stack1[midl]].time != s) {midr = midl + 1;} else {midl = midr - 1;}}solve1(l, midl);solve1(midr, r);ul tot = 0;bool flag = false;for (ul i = l; i <= midl; ++i) {if (v[stack1[i]].insert) {++tot;stack2[tot] = stack1[i];flag = true;}}if (!flag) {return;}flag = false;for (ul i = midr; i <= r; ++i) {if (!v[stack1[i]].insert) {++tot;stack2[tot] = stack1[i];flag = true;}}if (!flag) {return;}std::sort(stack2 + 1, stack2 + tot + 1, [](ul a, ul b){return v[a].pos < v[b].pos;});solve2(1, tot);}bool isquery[maxm + 1];int main(){std::scanf("%u%u", &n, &m);for (ul i = 1; i <= n; ++i) {std::scanf("%s", str + 1);ul curr = 1;for (ul i = 1; str[i]; ++i) {if (!tree[curr].ch[str[i] - 'a']) {++tot;tree[curr].ch[str[i] - 'a'] = tot;}curr = tree[curr].ch[str[i] - 'a'];}ptt[i] = curr;}search(1);tot = 0;for (ul i = 1; i <= n; ++i) {++tot;v[tot].insert = true;v[tot].val = 1;v[tot].time = 0;v[tot].pos = i;v[tot].dfn = dfn[ptt[i]];};for (ul t = 1; t <= m; ++t) {ul opt;std::scanf("%u", &opt);if (opt == 1) {ul i, j;std::scanf("%u%u", &i, &j);if (i == j) {continue;}++tot;v[tot].insert = true;v[tot].val = -1;v[tot].time = t;v[tot].pos = i;v[tot].dfn = dfn[ptt[i]];++tot;v[tot].insert = true;v[tot].val = -1;v[tot].time = t;v[tot].pos = j;v[tot].dfn = dfn[ptt[j]];std::swap(ptt[i], ptt[j]);++tot;v[tot].insert = true;v[tot].val = 1;v[tot].time = t;v[tot].pos = i;v[tot].dfn = dfn[ptt[i]];++tot;v[tot].insert = true;v[tot].val = 1;v[tot].time = t;v[tot].pos = j;v[tot].dfn = dfn[ptt[j]];} else {isquery[t] = true;ul k, l, r;std::scanf("%s%u%u%u", str + 1, &k, &l, &r);ul len = std::strlen(str + 1);if (k > len) {continue;}ul curr = 1;bool flag = true;for (ul i = 1; i <= k; ++i) {if (!tree[curr].ch[str[i] - 'a']) {flag = false;break;}curr = tree[curr].ch[str[i] - 'a'];}if (!flag) {continue;}++tot;v[tot].insert = false;v[tot].val = 1;v[tot].time = t;v[tot].pos = r + 1;v[tot].dfn = bdfn[curr] + 1;++tot;v[tot].insert = false;v[tot].val = -1;v[tot].time = t;v[tot].pos = l;v[tot].dfn = bdfn[curr] + 1;++tot;v[tot].insert = false;v[tot].val = -1;v[tot].time = t;v[tot].pos = r + 1;v[tot].dfn = dfn[curr];++tot;v[tot].insert = false;v[tot].val = 1;v[tot].time = t;v[tot].pos = l;v[tot].dfn = dfn[curr];}}for (ul i = 1; i <= tot; ++i) {stack1[i] = i;}solve1(1, tot);for (ul i = 1; i <= m; ++i) {if (isquery[i]) {std::printf("%u\n", ans[i]);}}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 card_t {public:ul suit = 0;ul number = 0;ul id = 0;card_t()=default;card_t(ul x): suit((x + 12) / 13), number((x - 1) % 13 + 1), id(x) {}};ul T;card_t deck[16];ul potcnt[6] = {0, 100, 100, 100, 100, 100};card_t holecards[6][3];card_t communitycards[6];ul state[6];std::pair<ul, ul> getvalue(card_t v[]){static std::pair<ul, ul> ret;if (v[1].suit == v[2].suit && v[1].suit == v[3].suit && v[1].suit == v[4].suit && v[1].suit == v[5].suit) {ret.first = 5;ret.second = v[5].number;if (v[1].number == 1) {ret.second = 14;}} else if (v[1].number + 1 == v[2].number && v[2].number + 1 == v[3].number && v[3].number + 1 == v[4].number && v[4].number + 1 == v[5].number || v[1].number == 1 && v[2].number == 10 && v[3].number == 11 && v[4].number == 12 && v[5].number == 13) {ret.first = 4;ret.second = v[5].number;if (v[1].number == 1 && v[5].number == 13) {ret.second = 14;}} else if (v[1].number == v[3].number || v[2].number == v[4].number || v[3].number == v[5].number) {ret.first = 3;for (ul i = 5; i >= 3; --i) {if (v[i].number == v[i - 2].number) {ret.second = v[i].number;break;}}if (v[1].number == v[3].number && v[1].number == 1) {ret.second = 14;}} else if (v[1].number == v[2].number || v[2].number == v[3].number || v[3].number == v[4].number || v[4].number == v[5].number) {ret.first = 2;for (ul i = 5; i >= 2; --i) {if (v[i].number == v[i - 1].number) {ret.second = v[i].number;break;}}if (v[1].number == v[2].number && v[1].number == 1) {ret.second = 14;}} else {ret.first = 1;ret.second = v[5].number;if (v[1].number == 1) {ret.second = 14;}}return ret;}std::vector<std::pair<ull, std::pair<ul, ul>>> map;std::vector<std::pair<ull, std::pair<ul, ul>>>::iterator find(ull x){auto it = std::lower_bound(map.begin(), map.end(), std::pair<ull, std::pair<ul, ul>>(x, std::pair<ul, ul>(0, 0)));if (it == map.end() || it->first != x) {return map.end();} else {return it;}}const std::pair<ul, ul>& at(ull x){return find(x)->second;}ull base;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::mt19937_64 rnd;card_t v1[6];card_t v2[6];ul v3[8];std::pair<ul, ul> ans[6];void getans(ul x){for (ul i = 1; i <= 5; ++i) {v3[i] = communitycards[i].id;}for (ul i = 1; i <= 2; ++i) {v3[i + 5] = holecards[x][i].id;}ans[x] = std::pair<ul, ul>(0, 0);for (ul i = 1; i + 1 <= 7; ++i) {for (ul j = i + 1; j <= 7; ++j) {ull hash = 1;for (ul k = 1; k <= 7; ++k) {if (k != i && k != j) {hash = gfmul(hash, base ^ v3[k]);}}ans[x] = std::max(ans[x], at(hash));}}}ul ord[53];int main(){for (ul i = 1; i <= 52; ++i) {ord[i] = i;}std::sort(ord + 1, ord + 53, [](ul a, ul b){return (a - 1) % 13 < (b - 1) % 13;});rnd.seed(std::time(0));base = rnd();for (ul a1 = 1; a1 + 4 <= 52; ++a1) {ull hash1 = base ^ ord[a1];v1[1] = ord[a1];for (ul a2 = a1 + 1; a2 + 3 <= 52; ++a2) {ull hash2 = gfmul(hash1, base ^ ord[a2]);v1[2] = ord[a2];for (ul a3 = a2 + 1; a3 + 2 <= 52; ++a3) {ull hash3 = gfmul(hash2, base ^ ord[a3]);v1[3] = ord[a3];for (ul a4 = a3 + 1; a4 + 1 <= 52; ++a4) {ull hash4 = gfmul(hash3, base ^ ord[a4]);v1[4] = ord[a4];for (ul a5 = a4 + 1; a5 <= 52; ++a5) {ull hash5 = gfmul(hash4, base ^ ord[a5]);v1[5] = ord[a5];map.push_back(std::pair<ull, std::pair<ul, ul>>(hash5, getvalue(v1)));}}}}}std::sort(map.begin(), map.end());std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {ul tot = 0;for (ul i = 1; i <= 15; ++i) {ul tmp;std::scanf("%u", &tmp);deck[i] = tmp;}ul alive = 0;ul last = 0;for (ul i = 1; i <= 5; ++i) {if (potcnt[i]) {++alive;++tot;holecards[i][1] = deck[tot];++tot;holecards[i][2] = deck[tot];}}std::memset(state, 0, sizeof(state));if (potcnt[1] > 0) {if (potcnt[1] >= 15 && holecards[1][1].suit == holecards[1][2].suit) {state[1] = 1;} else {last = 1;--alive;}}if (potcnt[2] > 0) {if (potcnt[2] >= 15) {state[2] = 1;} else if (holecards[2][1].number == 1 && holecards[2][2].number == 1) {state[2] = 3;} else {last = 2;--alive;}}if (potcnt[3] > 0) {if (holecards[3][1].number == 1 || holecards[3][2].number == 1 || std::max(holecards[3][1].number, holecards[3][2].number) - std::min(holecards[3][1].number, holecards[3][2].number) < 3) {state[3] = 1 + ul(potcnt[3] < 15) * 2;} else {last = 3;--alive;}}if (potcnt[4] > 0) {if (holecards[4][1].number > 11 || holecards[4][1].number == 1 || holecards[4][2].number > 11 || holecards[4][2].number == 1) {state[4] = 1 + ul(potcnt[4] < 15) * 2;} else {last = 4;--alive;}}if (potcnt[5] > 0) {if (ul(state[1] != 0) + ul(state[2] != 0) + ul(state[3] != 0) + ul(state[4] != 0) == 1) {state[5] = 1 + ul(potcnt[5] < 15) * 2;} else {last = 5;--alive;}}for (ul i = 1; i <= 3; ++i) {++tot;communitycards[i] = deck[tot];}if (state[1] == 1) {state[1] = 2;}if (state[2] == 1) {ull hashcurr = 1;for (ul i = 1; i <= 3; ++i) {hashcurr = gfmul(hashcurr, base ^ communitycards[i].id);v1[i] = communitycards[i];}for (ul i = 1; i <= 2; ++i) {hashcurr = gfmul(hashcurr, base ^ holecards[2][i].id);v1[i + 3] = holecards[2][i];}if (at(hashcurr).first >= 2) {state[2] = 2;} else {for (ul i = 1; i <= 5 && state[2] != 2; ++i) {ull hashcurr = 1;for (ul j = 1; j <= 5; ++j) {if (j != i) {hashcurr = gfmul(hashcurr, base ^ v1[j].id);}}for (ul t = 1; t <= 52; ++t) {ull hash = gfmul(hashcurr, base ^ t);auto it = find(hash);if (it != map.end() && it->second.first >= 4) {state[2] = 2;break;}}}}if (state[2] != 2) {--alive;last = 2;}}if (state[3] == 1) {bool flag = true;for (ul i = 1; i <= 3; ++i) {ul j = i + 1;if (j == 4) {j = 1;}if (communitycards[i].number == communitycards[j].number) {ul t = communitycards[i].number;bool flag2 = false;for (ul i = 1; i <= 2; ++i) {if (holecards[3][i].number == t) {flag2 = true;break;}}if (!flag2) {flag = false;break;}}}if (flag) {state[3] = 2;} else {--alive;last = 3;}}if (state[4] == 1) {ul maxcom = 0;for (ul i = 1; i <= 3; ++i) {if (communitycards[i].number == 1) {maxcom = 14;break;}maxcom = std::max(maxcom, communitycards[i].number);}ul maxhole = 0;for (ul i = 1; i <= 2; ++i) {if (holecards[4][i].number == 1) {maxhole = 14;break;}maxhole = std::max(maxhole, holecards[4][i].number);}if (maxhole >= maxcom) {state[4] = 2;} else {--alive;last = 4;}}if (state[5] == 1) {state[5] = 2;}for (ul i = 4; i <= 5; ++i) {++tot;communitycards[i] = deck[tot];}if (state[1] == 2) {getans(1);if (ans[1].first >= 2) {state[1] = 3;} else {--alive;last = 1;}}if (state[2] == 2) {bool flag = false;for (ul i = 1; i <= 5; ++i) {ul t = communitycards[1].suit;if (i == 1) {t = communitycards[2].suit;}bool flag2 = true;for (ul j = 1; j <= 5; ++j) {if (j == i) {continue;}if (communitycards[j].suit != t) {flag2 = false;break;}}if (flag2) {flag = true;break;}}if (!flag) {state[2] = 3;} else {--alive;last = 2;}}if (state[3] == 2) {state[3] = 3;}if (state[4] == 2) {getans(4);if (ans[4].first >= 3) {state[4] = 3;} else if (ans[4].first >= 2) {std::sort(communitycards + 1, communitycards + 6, [](const card_t& a, const card_t& b){return (a.number == 1) != (b.number == 1) ? b.number == 1 : a.number < b.number;});if (ans[4].second > communitycards[3].number && communitycards[3].number != 1) {state[4] = 3;}}if (state[4] != 3) {--alive;last = 4;}}if (state[5] == 2) {state[5] = 3;}std::pair<ul, ul> winval(0, 0);ul winner = 0;if (alive == 0) {winner = last;}for (ul i = 1; i <= 5; ++i) {if (state[i] == 3) {getans(i);if (winval <= ans[i]) {winval = ans[i];winner = i;}}}if (winner) {ul sum = 0;for (ul i = 1; i <= 5; ++i) {if (i != winner) {sum += std::min(potcnt[i], 5 * state[i]);potcnt[i] -= std::min(potcnt[i], 5 * state[i]);}}potcnt[winner] += sum;}}for (ul i = 1; i <= 5; ++i) {std::printf("%u\n", potcnt[i]);}return 0;}
我一直没搞懂这种题要严格证明最优性该从哪里入手。
策略是:如果只有公主一人,什么都不用问,如果支持者多于其他人,则挨着一直问公主在哪,问次,一定有一个答案出现了至少次,就是答案。
#include <bits/stdc++.h>using ul = std::uint32_t;using li = std::int32_t;using ull = std::uint64_t;using ll = std::int64_t;ul a, b, c;int main(){std::scanf("%u%u%u", &a, &b, &c);if (a == 1 && b == 0 && c == 0) {std::printf("YES\n0\n");} else if (a <= b + c) {std::printf("NO\n");} else {std::printf("YES\n%u\n", (b + c << 1) + 1);}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 mod = 1e9 + 7;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;}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;}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)));}ul n;ul cnt[51];std::unordered_map<ull, ul> ans;ull base;const ul maxn = 1e5;ul fac[maxn + 1];ul fiv[maxn + 1];ull hash = 1;ul sum;ul remain;ul search(){if (sum >= 50 || !remain) {return fac[remain];}auto it = ans.find(hash);if (it != ans.end()) {return it->second;}ul tmp = 0;for (ul i = 1; i <= sum; ++i) {if (!cnt[i]) {continue;}--cnt[i];sum += i;--remain;ull chash = hash;hash = gfmul(hash, base ^ i);ul t = search();++cnt[i];sum -= i;++remain;hash = chash;tmp = plus(tmp, mul(cnt[i], t));}ans[hash] = tmp;return tmp;}std::mt19937_64 rnd;int main(){rnd.seed(std::time(0));base = rnd();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);}std::scanf("%u", &n);std::scanf("%u", &sum);for (ul i = 1; i <= n; ++i) {ul a;std::scanf("%u", &a);++cnt[a];if (a) {++remain;}}ul tmp = search();std::printf("%u\n", mul(tmp, mul(fac[n], fiv[remain])));return 0;}
关于最小权匹配的算法:https://www.zybuluo.com/qq290637843/note/1774018。
#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 pllul = std::pair<ll, ul>;ul n;const ul maxn = 400;ll a[maxn + 1];ul p[maxn + 1];ll b[maxn + 1];ll c[maxn + 1];ul ord[maxn + 1];std::vector<pllul> sum;const ll inf = ll(2e18) + 1;ll w[maxn + 1][maxn + 1];ul x[maxn + 1];ul y[maxn + 1];void lapjv(ul n, const ll c[][maxn + 1], ul x[maxn + 1], ul y[maxn + 1]){static ll u[maxn + 1];static ll v[maxn + 1];static ll d[maxn + 1];static ul pred[maxn + 1];static bool vis[maxn + 1];std::memset(u + 1, 0, sizeof(ll) * n);std::memset(x + 1, 0, sizeof(ul) * n);std::memset(y + 1, 0, sizeof(ul) * n);for (ul j = 1; j <= n; ++j) {v[j] = 0;for (ul i = 1; i <= n; ++i) {v[j] = std::min(v[j], c[i][j]);}}for (ul istar = 1; istar <= n; ++istar) {for (ul j = 1; j <= n; ++j) {d[j] = c[istar][j] - u[istar] - v[j];pred[j] = istar;vis[j] = false;}ul endj;ll mu;while (true) {ul jstar;mu = inf;for (ul j = 1; j <= n; ++j) {if (!vis[j] && mu > d[j]) {jstar = j;mu = d[j];}}if (!y[jstar]) {endj = jstar;break;}vis[jstar] = true;ul i = y[jstar];for (ul j = 1; j <= n; ++j) {if (mu + c[i][j] - u[i] - v[j] < d[j]) {d[j] = mu + c[i][j] - u[i] - v[j];pred[j] = i;}}}for (ul k = 1; k <= n; ++k) {if (d[k] < mu) {v[k] -= mu - d[k];}}ul j = endj;while (true) {ul i = pred[j];y[j] = i;std::swap(j, x[i]);if (i == istar) {break;}}for (ul i = 1; i <= istar; ++i) {u[i] = c[i][x[i]] - v[x[i]];}}}int main(){std::scanf("%u", &n);for (ul i = 1; i <= n; ++i) {std::scanf("%lld", &a[i]);ord[i] = i;}for (ul i = 1; i <= n; ++i) {std::scanf("%lld", &p[i]);}std::sort(ord + 1, ord + n + 1, [](ul x, ul y){return a[x] < a[y];});sum.push_back(pllul(-inf, 0));for (ul i = 1; i <= n; ++i) {if (a[ord[i]] != sum.back().first) {sum.push_back(pllul(a[ord[i]], sum.back().second));}sum.back().second += p[ord[i]];}for (ul i = 1; i <= n; ++i) {std::scanf("%lld", &b[i]);}for (ul i = 1; i <= n; ++i) {std::scanf("%lld", &c[i]);}for (ul i = 1; i <= n; ++i) {for (ul j = 1; j <= n; ++j) {w[i][j] = -ll(std::prev(std::lower_bound(sum.begin(), sum.end(), pllul(b[i] + c[j], 0)))->second);}}lapjv(n, w, x, y);ll ans = 0;for (ul i = 1; i <= n; ++i) {ans -= w[i][x[i]];}std::printf("%lld\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;class vec {public:lf x = 0;lf y = 0;vec()=default;vec(lf x, lf y): x(x), y(y) {}};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);}lf operator*(const vec& a, const vec& b){return a.x * b.x + a.y * b.y;}lf operator^(const vec& a, const vec& b){return a.x * b.y - a.y * b.x;}vec operator*(lf a, const vec& b){return vec(a * b.x, a * b.y);}ul T;vec a, b, c, p, q;int main(){std::scanf("%u", &T);for (ul Case = 1; Case <= T; ++Case) {std::scanf("%lf%lf%lf%lf%lf%lf%lf%lf", &a.x, &a.y, &b.x, &b.y, &c.x, &c.y, &p.x, &p.y);if (!(a - p ^ b - p) && (a - p) * (b - p) <= 0) {} else if (!(a - p ^ c - p) && (a - p) * (b - p) <= 0) {std::swap(b, c);} else if (!(b - p ^ c - p) && (b - p) * (c - p) <= 0) {std::swap(a, b);} else {std::printf("-1\n");continue;}if ((a - c ^ b - c) < 0) {std::swap(a, b);}lf s = a - c ^ p - c;lf t = p - c ^ b - c;if (s == t) {q = c;} else if (s < t) {q = lf(0.5) * (s + t) / (c - b ^ p - b) * (c - b) + b;} else {q = lf(0.5) * (s + t) / (p - a ^ c - a) * (c - a) + a;}std::printf("%.20lf %.20lf\n", q.x, q.y);}return 0;}