模拟。
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
int n, m;
cin >> n >> m;
vector<pair<int, int>> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i].first;
}
for (int i = 0; i < n; ++i) {
cin >> a[i].second;
}
sort(a.begin(), a.end());
int ans = 0;
while (ans < n && m >= a[ans].second) {
m -= a[ans++].second;
}
cout << "Case " << qq << ": " << ans << "\n";
}
return 0;
}
建出图,如果图不是二分图,则无解。否则枚举最大值,用堆维护最小值的最大可能值。
#include
using namespace std;
const int inf = 0x3f3f3f3f;
class heap {
priority_queue<int, vector<int>, greater<int>> p, q;
public:
void push(int x) {
p.push(x);
}
void pop(int x) {
q.push(x);
}
int top() {
while (!q.empty() && p.top() == q.top()) {
p.pop();
q.pop();
}
return p.top();
}
};
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
int n, m;
cin >> n >> m;
vector<vector<int>> adj(n);
for (int i = 0; i < m; ++i) {
int from, to;
cin >> from >> to;
--from;
--to;
adj[from].push_back(to);
adj[to].push_back(from);
}
vector<vector<int>> a(n, vector<int>(2));
for (int i = 0; i < n; ++i) {
cin >> a[i][0] >> a[i][1];
}
bool no_solution = false;
vector<int> sz(n);
vector<int> cur(n);
vector<int> min_id(n);
vector<int> color(n, -1);
vector<vector<int>> cnt(n, vector<int>(2));
vector<vector<int>> minv(n, vector<int>(2, inf));
heap h;
for (int i = 0; i < n; ++i) {
if (color[i] == -1) {
h.push(cur[i] = -inf);
queue<int> q;
color[i] = 0;
min_id[i] = i;
++sz[i];
q.push(i);
while (!q.empty()) {
int x = q.front();
q.pop();
minv[i][color[x]] = min(minv[i][color[x]], a[x][0]);
minv[i][!color[x]] = min(minv[i][!color[x]], a[x][1]);
for (auto y : adj[x]) {
if (color[y] == -1) {
color[y] = !color[x];
min_id[y] = i;
++sz[i];
q.push(y);
} else if (color[y] == color[x]) {
no_solution = true;
break;
}
}
}
if (no_solution) {
break;
}
}
}
if (no_solution) {
cout << "Case " << qq << ": IMPOSSIBLE" << "\n";
continue;
}
int ans = inf;
vector<pair<int, int>> events(n * 2);
for (int i = 0; i < n; ++i) {
events[i * 2] = make_pair(a[i][0], i);
events[i * 2 + 1] = make_pair(a[i][1], i + n);
}
sort(events.begin(), events.end());
for (auto p : events) {
int x = p.second;
if (x >= n) {
x -= n;
if (++cnt[min_id[x]][!color[x]] == sz[min_id[x]]) {
h.pop(cur[min_id[x]]);
cur[min_id[x]] = max(cur[min_id[x]], minv[min_id[x]][!color[x]]);
h.push(cur[min_id[x]]);
}
} else {
if (++cnt[min_id[x]][color[x]] == sz[min_id[x]]) {
h.pop(cur[min_id[x]]);
cur[min_id[x]] = max(cur[min_id[x]], minv[min_id[x]][color[x]]);
h.push(cur[min_id[x]]);
}
}
ans = min(ans, p.first - h.top());
}
cout << "Case " << qq << ": " << ans << "\n";
}
return 0;
}
记 m m m 为 n 2 \frac{n}{2} 2n ,令 m m m 的编号 x x x 为不超过 m m m 的素数的乘积,那么此时只有 m + 1 m+1 m+1 和 m − 1 m-1 m−1 没有连起来;考虑去掉 m m m 以内的最大的两个质数 p , q p, q p,q ,用它们去连 1 1 1 和 − 1 -1 −1 (即 x − 1   m o d   p = 0 , x + 1   m o d   q = 0 x-1\bmod p=0, x+1\bmod q=0 x−1modp=0,x+1modq=0 ),此时 m − p , m − q , m + p , m + q m-p, m-q, m+p, m+q m−p,m−q,m+p,m+q 没有被连起来;注意到我们还没有用大于 m m m 的质数,用这些质数连起来,最后CRT合并即可。这个做法需要特判 n ≤ 38 n\le 38 n≤38 的数据。
to_multiply = []
table = [-1, 1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 2183, 27828, 27827, 87889, 87889, 171053, 171053, 323509, 127373, 323509, 151061, 151061, 151061, 151060, 151059, 151058, 151057, 672540170261, 672540170261, 2101641443861, 2101641443861, 4152621523030]
def inv(a, md):
b, u, v = md, 0, 1
while a:
t = b / a
a, b = b - t * a, a
v, u = u - t * v, v
if u < 0:
u += md
return u
def crt(m, a):
mm, aa = m[0], a[0]
for i in range(1, len(m)):
mm, aa = mm * m[i], (aa * m[i] * inv(m[i], mm) + a[i] * mm * inv(mm, m[i])) % (mm * m[i])
return aa
def multiply_all(l, r):
if l > r:
return 1
elif l == r:
return to_multiply[l]
else:
m = (l + r) / 2
return multiply_all(l, m) * multiply_all(m + 1, r)
tt = int(raw_input())
for qq in range(1, tt + 1):
n = int(raw_input())
if n < 39:
ans = table[n]
else:
prime = [True] * (n + 1)
for i in range(2, n + 1):
for j in range(i + i, n + 1, i):
prime[j] = False
m = (n + 1) / 2
to_multiply = []
for i in range(2, m):
if prime[i]:
to_multiply.append(i)
p, q = to_multiply[-2], to_multiply[-1]
to_multiply = to_multiply[:-2]
if m * 2 == n and prime[m]:
to_multiply.append(m)
r = []
for i in range(n - m + 1, n):
if prime[i]:
r.append(i)
if len(r) == 4:
break
ans = crt([multiply_all(0, len(to_multiply) - 1), p, q, r[0], r[1], r[2], r[3]], [0, 1, q - 1, p, r[1] - p, q, r[3] - q]) - m
print "Case " + str(qq) + ": " + str(ans)
记 a x a_x ax 表示父亲已经不能走了, x x x 是第一次经过时的期望答案; b x b_x bx 表示父亲已经不能走了, x x x 是第二次经过时的期望答案; c x c_x cx 表示父亲可以走,在 x x x 子树内先走了一步(没有立刻返回父亲)并在子树内停下来时的期望答案; d x d_x dx 表示父亲可以走,在 x x x 子树内先走了一步(没有立刻返回父亲)并在子树内停下来时的概率; e x e_x ex 表示父亲可以走,在 x x x 子树内先走了一步(没有立刻返回父亲)并走出子树的概率。转移自行脑补。
#include
using namespace std;
const int md = (int) (1e9 + 7);
inline void add(int &x, int y) {
x += y;
if (x >= md) {
x -= md;
}
}
inline void sub(int &x, int y) {
x -= y;
if (x < 0) {
x += md;
}
}
inline int mul(int x, int y) {
return (int) ((long long) x * y % md);
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
int n;
cin >> n;
vector<int> v(n);
for (int i = 0; i < n; ++i) {
cin >> v[i];
}
vector<vector<int>> adj(n);
for (int i = 0; i < n - 1; ++i) {
int from, to;
cin >> from >> to;
--from;
--to;
adj[from].push_back(to);
adj[to].push_back(from);
}
vector<int> invs(n + 1);
invs[0] = invs[1] = 1;
for (int i = 2; i <= n; ++i) {
invs[i] = mul(md - md / i, invs[md % i]);
}
vector<int> a(n);
vector<int> b(n);
vector<int> c(n);
vector<int> d(n);
vector<int> e(n);
vector<int> g(n);
function<void(int, int)> dfs = [&](int x, int p) {
if (p != -1) {
adj[x].erase(find(adj[x].begin(), adj[x].end(), p));
}
if (adj[x].empty()) {
a[x] = b[x] = v[x];
} else {
g[x] = adj[x].size();
int sum = 0;
for (auto y : adj[x]) {
dfs(y, x);
add(sum, a[y]);
}
b[x] = mul(sum, invs[g[x]]);
for (auto y : adj[x]) {
add(a[x], mul(c[y], invs[g[x]]));
add(a[x], mul(((sum - a[y] + b[y]) % md + md) % md, mul(invs[g[y] + 1], mul(invs[g[x]], invs[g[x]]))));
add(a[x], mul(e[y], mul(g[x] == 1 ? v[x] : mul((sum - a[y] + md) % md, invs[g[x] - 1]), invs[g[x]])));
add(c[x], mul(c[y], invs[g[x] + 1]));
add(c[x], mul(((sum - a[y] + b[y]) % md + md) % md, mul(invs[g[y] + 1], mul(invs[g[x] + 1], invs[g[x] + 1]))));
add(c[x], mul(e[y], mul((sum - a[y] + md) % md, mul(invs[g[x]], invs[g[x] + 1]))));
add(d[x], mul(d[y], invs[g[x] + 1]));
add(d[x], mul(g[x], mul(invs[g[y] + 1], mul(invs[g[x] + 1], invs[g[x] + 1]))));
add(d[x], mul(e[y], mul(g[x] - 1, mul(invs[g[x]], invs[g[x] + 1]))));
}
e[x] = 1;
sub(e[x], d[x]);
sub(e[x], invs[g[x] + 1]);
}
};
int root;
cin >> root;
--root;
dfs(root, -1);
cout << "Case " << qq << ": " << a[root] << "\n";
}
return 0;
}
对于一棵树的情况,直接选出 k − 1 k-1 k−1 条权值最小的边即可;对于一个环,如果环上颜色不完全相同,则至少要选出两条边。对这个做背包即可。
这个题有点卡空间,可以用哈夫曼树优化合并背包得到更优的空间复杂度。
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
int n, m, k;
cin >> n >> m >> k;
vector<int> from(m), to(m), cost(m);
vector<vector<int>> adj(n);
for (int i = 0; i < m; ++i) {
cin >> from[i] >> to[i] >> cost[i];
--from[i];
--to[i];
adj[from[i]].push_back(i);
adj[to[i]].push_back(i);
}
vector<vector<pair<long long, pair<int, int>>>> cycles;
vector<int> pe(n, -1);
vector<int> depth(n);
vector<bool> on(m);
function<void(int)> dfs = [&](int x) {
for (auto e : adj[x]) {
if (e != pe[x]) {
int y = from[e] + to[e] - x;
if (!depth[y]) {
depth[y] = depth[x] + 1;
pe[y] = e;
dfs(y);
} else if (depth[x] < depth[y]) {
vector<int> edges;
int z = y;
while (z != x) {
edges.push_back(pe[z]);
on[pe[z]] = true;
z = from[pe[z]] + to[pe[z]] - z;
}
edges.push_back(e);
on[e] = true;
sort(edges.begin(), edges.end(), [&](int a, int b) {
return cost[a] < cost[b];
});
cycles.emplace_back();
cycles.back().emplace_back(cost[edges[0]] + cost[edges[1]], make_pair(edges[0], edges[1]));
for (int i = 2; i < (int) edges.size(); ++i) {
cycles.back().emplace_back(cost[edges[i]], make_pair(edges[i], -1));
}
}
}
}
};
int need = k;
for (int i = 0; i < n; ++i) {
if (!depth[i]) {
depth[i] = 1;
dfs(i);
--need;
}
}
need = max(need, 0);
vector<int> edges;
for (int i = 0; i < m; ++i) {
if (!on[i]) {
edges.push_back(i);
}
}
sort(edges.begin(), edges.end(), [&](int a, int b) {
return cost[a] < cost[b];
});
cycles.emplace_back();
for (auto e : edges) {
cycles.back().emplace_back(cost[e], make_pair(e, -1));
}
vector<vector<long long>> dp(cycles.size());
for (int i = 0; i < (int) cycles.size(); ++i) {
long long cur = 0;
dp[i].push_back(cur);
for (int j = 0; j < (int) cycles[i].size() && j < need; ++j) {
cur += cycles[i][j].first;
dp[i].push_back(cur);
}
}
vector<int> left(cycles.size(), -1), right(cycles.size(), -1);
set<pair<int, int>> huffman;
for (int i = 0; i < (int) cycles.size(); ++i) {
huffman.emplace(dp[i].size(), i);
}
while ((int) huffman.size() > 1) {
int x = huffman.begin()->second;
huffman.erase(huffman.begin());
int y = huffman.begin()->second;
huffman.erase(huffman.begin());
int z = dp.size();
dp.push_back(vector<long long>(min((int) dp[x].size() + (int) dp[y].size() - 1, need + 1), 1ll << 60));
for (int i = 0; i < (int) dp[x].size(); ++i) {
for (int j = 0; j < (int) dp[y].size(); ++j) {
if (i + j <= need) {
dp[z][i + j] = min(dp[z][i + j], dp[x][i] + dp[y][j]);
}
}
}
left.push_back(x);
right.push_back(y);
huffman.emplace(dp[z].size(), z);
}
vector<bool> bad(m);
function<void(int, int)> push = [&](int z, int need) {
if (!need) {
return;
}
if (z < (int) cycles.size()) {
for (int i = 0; i < need; ++i) {
bad[cycles[z][i].second.first] = true;
if (cycles[z][i].second.second != -1) {
bad[cycles[z][i].second.second] = true;
}
}
} else {
int x = left[z];
int y = right[z];
for (int i = max(0, need - (int) dp[y].size() + 1); i < (int) dp[x].size() && i <= need; ++i) {
if (dp[x][i] + dp[y][need - i] == dp[z][need]) {
push(x, i);
push(y, need - i);
return;
}
}
}
};
push(dp.size() - 1, need);
cout << "Case " << qq << ": " << dp.back()[need] << "\n";
vector<int> ans(n, -1);
function<void(int, int)> color = [&](int x, int c) {
ans[x] = c;
for (auto e : adj[x]) {
if (!bad[e]) {
int y = from[e] + to[e] - x;
if (ans[y] == -1) {
color(y, c);
}
}
}
};
int cur = 0;
for (int i = 0; i < n; ++i) {
if (ans[i] == -1) {
color(i, cur++);
if (cur == k) {
cur = 0;
}
}
}
for (int i = 0; i < n; ++i) {
if (i) {
cout << " ";
}
cout << ans[i] + 1;
}
cout << "\n";
}
return 0;
}
求出V图之后积分即可。
#include
using namespace std;
typedef double ld;
const ld inf = 1e2;
const ld eps = 1e-9;
const ld pi = acos(-1);
struct point {
ld x, y;
point(ld x = 0, ld y = 0): x(x), y(y) {
}
point operator + (const point &other) const {
return point(x + other.x, y + other.y);
}
point operator - (const point &other) const {
return point(x - other.x, y - other.y);
}
point operator * (const ld &ratio) const {
return point(x * ratio, y * ratio);
}
point operator / (const ld &ratio) const {
return point(x / ratio, y / ratio);
}
};
ld dot(point a, point b) {
return a.x * b.x + a.y * b.y;
}
ld cross(point a, point b) {
return a.x * b.y - a.y * b.x;
}
ld dist(point a, point b) {
return sqrt(dot(a - b, a - b));
}
bool on_segment(point p, point a, point b) {
return dot(a - p, b - p) < -eps;
}
point project(point p, point a, point b) {
point d = b - a;
return a + d * (dot(p - a, d) / dot(d, d));
}
vector<point> intersect_circle_line(point p, ld r, point a, point b) {
point c = project(p, a, b);
ld d = r * r - dot(c - p, c - p);
if (d < -eps) {
return vector<point>();
} else if (d < eps) {
return vector<point>(1, c);
}
point e = (b - a) / dist(a, b) * sqrt(d);
return vector<point>{c + e, c - e};
}
vector<vector<point>> voronoi(vector<point> p) {
int n = (int) p.size();
vector<vector<point>> ans(n);
for (int i = 0; i < n; ++i) {
ans[i].emplace_back(-inf, -inf);
ans[i].emplace_back(inf, -inf);
ans[i].emplace_back(inf, inf);
ans[i].emplace_back(-inf, inf);
for (int j = 0; j < n; ++j) {
if (j != i) {
ld a = p[j].x - p[i].x, b = p[j].y - p[i].y, c = -0.5 * (a * (p[i].x + p[j].x) + b * (p[i].y + p[j].y));
vector<point> bound;
ans[i].push_back(ans[i][0]);
for (int k = 0; k + 1 < (int) ans[i].size(); ++k) {
ld v = a * ans[i][k].x + b * ans[i][k].y + c;
if (v < eps) {
bound.push_back(ans[i][k]);
}
ld u = a * ans[i][k + 1].x + b * ans[i][k + 1].y + c;
if ((v < -eps && u > eps) || (v > eps && u < -eps)) {
ld aa = ans[i][k + 1].y - ans[i][k].y, bb = ans[i][k].x - ans[i][k + 1].x, cc = -(aa * ans[i][k].x + bb * ans[i][k].y), dd = aa * b - bb * a;
bound.emplace_back((bb * c - cc * b) / dd, (cc * a - aa * c) / dd);
}
}
swap(ans[i], bound);
}
}
}
return ans;
}
ld integral(ld a, ld c) {
ld b = sqrt(c * c - a * a);
ld all = (1 - c) * a * b;
ld triangle = 1.0 / 2 * a * (c * b - a * a * log(b + c) + a * a * log(a));
ld circle = 1.0 / 6 * a * (c * b + a * a * log(b + c) - a * a * log(a));
return all + triangle + circle;
}
ld solve(point a, point b) {
ld h = fabs(cross(a, b)) / dist(a, b);
if (dot(a, b - a) > eps) {
return integral(h, sqrt(dot(b, b))) - integral(h, sqrt(dot(a, a)));
} else if (dot(b, a - b) > eps) {
return integral(h, sqrt(dot(a, a))) - integral(h, sqrt(dot(b, b)));
} else {
return integral(h, sqrt(dot(a, a))) + integral(h, sqrt(dot(b, b)));
}
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cout.setf(ios::fixed);
cout.precision(15);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
int n;
cin >> n;
vector<point> p(n);
for (int i = 0; i < n; ++i) {
cin >> p[i].x >> p[i].y;
}
random_shuffle(p.begin(), p.end());
vector<vector<point>> bound = voronoi(p);
ld ans = 0;
for (int i = 0; i < n; ++i) {
for (int j = 0; j < (int) bound[i].size(); ++j) {
point a = bound[i][j], b = bound[i][(j + 1) % bound[i].size()];
vector<point> q = intersect_circle_line(p[i], 1, a, b);
vector<point> new_q;
new_q.push_back(a);
for (auto p : q) {
if (on_segment(p, a, b)) {
new_q.push_back(p);
}
}
new_q.push_back(b);
if ((int) new_q.size() == 4 && cross(new_q[1] - p[i], new_q[2] - p[i]) < 0) {
swap(new_q[1], new_q[2]);
}
swap(q, new_q);
for (int k = 0; k + 1 < (int) q.size(); ++k) {
point a = q[k], b = q[k + 1];
if (dist(p[i], a) + dist(p[i], b) < 2 + eps) {
ans += solve(a - p[i], b - p[i]);
} else {
ld angle = atan2(b.y - p[i].y, b.x - p[i].x) - atan2(a.y - p[i].y, a.x - p[i].x);
if (angle < -eps) {
angle += pi * 2;
}
ans += angle / 3;
}
}
}
}
cout << "Case " << qq << ": " << ans / 2 << "\n";
}
return 0;
}
暴力。
#include
using namespace std;
const int N = (int) 1e5;
const int md = (int) (1e9 + 7);
inline void add(int &x, int y) {
x += y;
if (x >= md) {
x -= md;
}
}
inline void sub(int &x, int y) {
x -= y;
if (x < 0) {
x += md;
}
}
inline int mul(int x, int y) {
return (int) ((long long) x * y % md);
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
vector<int> foo(N + 1);
vector<int> bar(N + 1);
for (int i = 3; i <= N; ++i) {
foo[i] = foo[i - 1];
add(foo[i], mul(i - 2, i - 1));
bar[i] = bar[i - 1];
add(bar[i], mul(i - 2, mul(i - 1, i - 1)));
}
for (int qq = 1; qq <= tt; ++qq) {
int n, m;
cin >> n >> m;
int ans_n = mul(foo[n], n);
sub(ans_n, bar[n]);
int ans_m = mul(foo[m], m);
sub(ans_m, bar[m]);
cout << "Case " << qq << ": " << mul((md + 1) / 4, mul(ans_n, ans_m)) << "\n";
}
return 0;
}
记 d s i ds_i dsi 表示 Panda 的起点到 i i i 的距离, d t i dt_i dti 表示 Sheep 的起点到 i i i 的距离,分几种情况讨论:
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
int n;
cin >> n;
vector<vector<int>> adj(n);
vector<int> deg(n);
for (int i = 0; i < n; ++i) {
int from, to;
cin >> from >> to;
--from;
--to;
adj[from].push_back(to);
adj[to].push_back(from);
++deg[from];
++deg[to];
}
int m;
cin >> m;
vector<int> ed(m);
for (int i = 0; i < m; ++i) {
cin >> ed[i];
--ed[i];
}
int s, t;
cin >> s >> t;
--s;
--t;
vector<bool> tree(n);
queue<int> q;
for (int i = 0; i < n; ++i) {
if (deg[i] <= 1) {
tree[i] = true;
q.push(i);
}
}
while (!q.empty()) {
int x = q.front();
q.pop();
for (auto y : adj[x]) {
if (!tree[y] && --deg[y] <= 1) {
tree[y] = true;
q.push(y);
}
}
}
vector<int> id(n, -1);
vector<int> cycle;
for (int i = 0; i < n; ++i) {
if (!tree[i]) {
int x = i;
id[x] = cycle.size();
cycle.push_back(x);
while (true) {
int to = -1;
for (auto y : adj[x]) {
if (!tree[y] && id[y] == -1) {
to = y;
id[y] = cycle.size();
cycle.push_back(y);
break;
}
}
if (to == -1) {
break;
}
x = to;
}
break;
}
}
m = cycle.size();
vector<int> top(n, -1);
function<void(int, int, int)> dfs = [&](int x, int p, int c) {
top[x] = c;
for (auto y : adj[x]) {
if (tree[y] && y != p) {
dfs(y, x, c);
}
}
};
for (int i = 0; i < m; ++i) {
dfs(cycle[i], -1, i);
}
auto bfs = [&](int s) {
vector<int> dist(n, -1);
queue<int> q;
dist[s] = 0;
q.push(s);
while (!q.empty()) {
int x = q.front();
q.pop();
for (auto y : adj[x]) {
if (dist[y] == -1) {
dist[y] = dist[x] + 1;
q.push(y);
}
}
}
return dist;
};
vector<int> ds = bfs(s), dt = bfs(t);
bool win = false;
for (auto x : ed) {
if (ds[x] <= dt[x]) {
win = true;
break;
}
}
if (win) {
cout << "Case " << qq << ": Panda" << "\n";
continue;
}
int u = top[s], v = top[t];
if (ds[cycle[u]] > dt[cycle[u]]) {
cout << "Case " << qq << ": Sheep" << "\n";
continue;
}
int l = m, r = m;
for (auto x : ed) {
if (top[x] != v) {
l = min(l, (u - top[x] + m) % m);
r = min(r, (top[x] - u + m) % m);
}
}
if (l == m) {
cout << "Case " << qq << ": Sheep" << "\n";
continue;
}
int ll = (u - l + m) % m, rr = (u + r) % m, between = min(l + r, m - (l + r));
if (dt[ll] + between < ds[rr] || dt[rr] + between < ds[ll] || l + r > m - (l + r) + 1) {
cout << "Case " << qq << ": Sheep" << "\n";
} else {
cout << "Case " << qq << ": Panda" << "\n";
}
}
return 0;
}
拿行最大值和列最大值随便讨论一下就好了。
#include
using namespace std;
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
int n;
cin >> n;
vector<int> x(n), y(n);
unordered_map<int, int> cx, cy;
for (int i = 0; i < n; ++i) {
cin >> x[i] >> y[i];
++cx[x[i]];
++cy[y[i]];
}
int tx = 0, ty = 0, wx = 0, wy = 0;
for (auto p : cx) {
if (tx < p.second) {
tx = p.second;
wx = 1;
} else if (tx == p.second) {
++wx;
}
}
for (auto p : cy) {
if (ty < p.second) {
ty = p.second;
wy = 1;
} else if (ty == p.second) {
++wy;
}
}
int ans = tx + ty;
long long ways = (long long) wx * wy;
for (int i = 0; i < n; ++i) {
if (cx[x[i]] + cy[y[i]] == ans) {
--ways;
}
}
if (!ways) {
--ans;
ways = (long long) wx * wy;
for (auto p : cx) {
if (p.second == tx - 1) {
ways += wy;
}
}
for (auto p : cy) {
if (p.second == ty - 1) {
ways += wx;
}
}
for (int i = 0; i < n; ++i) {
if (cx[x[i]] + cy[y[i]] == ans) {
--ways;
}
}
}
if (ans == 1) {
ways = n;
} else if (ans == 2) {
ways = (long long) n * (n - 1) / 2;
}
cout << "Case " << qq << ": " << ans << " " << ways << "\n";
}
return 0;
}
因为可以翻转的前缀长度需要递增,所以对于一个可以翻转的位置到下一个位置,有两种方案,二分哈希比较即可。
#include
using namespace std;
const int md0 = (int) (1e9 + 7);
const int md1 = (int) (1e9 + 9);
inline int inv(int a, int md) {
int b = md, u = 0, v = 1;
while (a) {
int t = b / a;
b -= t * a;
swap(a, b);
u -= t * v;
swap(u, v);
}
if (u < 0) {
u += md;
}
return u;
}
struct hashv {
int h0, h1;
hashv(int h0 = 0, int h1 = 0): h0(h0), h1(h1) {
}
hashv operator * (const hashv &x) const {
return hashv((long long) h0 * x.h0 % md0, (long long) h1 * x.h1 % md1);
}
hashv operator + (const hashv &x) const {
return hashv((h0 + x.h0) % md0, (h1 + x.h1) % md1);
}
hashv operator - (const hashv &x) const {
return hashv((h0 + md0 - x.h0) % md0, (h1 + md1 - x.h1) % md1);
}
inline long long get() {
return (long long) h0 * md1 + h1;
}
};
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
int n, m;
cin >> n >> m;
vector<int> a(n);
for (int i = 0; i < n; ++i) {
cin >> a[i];
}
vector<bool> ban(n);
while (m--) {
int x;
cin >> x;
--x;
ban[x] = true;
}
vector<hashv> p(n * 2);
vector<hashv> inv_p(n * 2);
p[0] = inv_p[0] = hashv(1, 1);
hashv base(2333, 2333);
hashv inv_base(inv(2333, md0), inv(2333, md1));
for (int i = 1; i < n * 2; ++i) {
p[i] = p[i - 1] * base;
inv_p[i] = inv_p[i - 1] * inv_base;
}
vector<hashv> pref(n * 2 + 1);
auto query = [&](int l, int r) {
return ((pref[r] - pref[l]) * inv_p[l]).get();
};
vector<int> b(n * 2);
int l0 = n, r0 = n, l1 = n, r1 = n;
for (int i = 0; i < n; ++i) {
b[r1] = a[i];
pref[r1 + 1] = pref[r1] + p[r1] * a[i];
++r1;
--l0;
b[l0] = a[i];
pref[l0] = pref[l0 + 1] - p[l0] * a[i];
if (!ban[i]) {
int l = 0, r = r0 - l0;
while (l < r) {
int mid = (l + r + 1) >> 1;
if (query(l0, l0 + mid) == query(l1, l1 + mid)) {
l = mid;
} else {
r = mid - 1;
}
}
if (l == r0 - l0 || b[l0 + l] < b[l1 + l]) {
l1 = l0;
r1 = r0;
} else {
l0 = l1;
r0 = r1;
}
}
}
int ans = 0;
for (int i = r1 - 1; i >= l1; --i) {
ans = (37ll * ans + b[i]) % 20181125;
}
cout << "Case " << qq << ": " << ans << "\n";
}
return 0;
}
因为数据随机,所以可以直接在 n \sqrt n n 附近快速找出 p p p 和 q q q 。注意到 2 30 + 3 2^{30}+3 230+3 是质数,所以快速幂是可逆的,CRT合并即可。
#include
using namespace std;
const int e = (1 << 30) + 3;
inline int power(int x, int y, int md) {
int res = 1;
while (y) {
if (y & 1) {
res = (long long) res * x % md;
}
x = (long long) x * x % md;
y >>= 1;
}
return res;
}
inline int inv(int a, int md) {
int b = md, u = 0, v = 1;
while (a) {
int t = b / a;
b -= t * a;
swap(a, b);
u -= t * v;
swap(u, v);
}
if (u < 0) {
u += md;
}
return u;
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
long long n, c;
cin >> n >> c;
int p = sqrt(n);
while (n % p) {
--p;
}
int q = n / p;
int u = power(c % p, inv(e % (p - 1), p - 1), p);
int v = power(c % q, inv(e % (q - 1), q - 1), q);
long long ans = ((long long) u * inv(q, p) % p * q + (long long) v * inv(p, q) % q * p) % n;
cout << "Case " << qq << ": " << ans << "\n";
}
return 0;
}
哥德巴赫猜想,直接暴力枚举质数找解即可。
#include
using namespace std;
bool check(long long n) {
for (int i = 2; (long long) i * i <= n; ++i) {
if (n % i == 0) {
return false;
}
}
return true;
}
int main() {
#ifdef wxh010910
freopen("input.txt", "r", stdin);
#endif
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
int tt;
cin >> tt;
for (int qq = 1; qq <= tt; ++qq) {
long long n;
cin >> n;
if (n >= 12) {
if (n & 1) {
n -= 9;
for (int i = 2; ; ++i) {
if (check(i) && check(n - i)) {
cout << "Case " << qq << ": 2 2 2 3 " << i << " " << n - i << "\n";
break;
}
}
} else {
n -= 8;
for (int i = 2; ; ++i) {
if (check(i) && check(n - i)) {
cout << "Case " << qq << ": 2 2 2 2 " << i << " " << n - i << "\n";
break;
}
}
}
} else {
cout << "Case " << qq << ": IMPOSSIBLE" << "\n";
}
}
return 0;
}