Digits Sum
暴力。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
inline int S(int x) {
int r = 0;
while (x) {
r += x % 10, x /= 10;
}
return r;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
int n;
Read(n);
int ans = INT_MAX;
for (int i = 1; i < n; ++i) {
CheckMin(ans, S(i) + S(n - i));
}
printf("%d\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
RGB Coloring
暴力。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 300005;
const int mod = 998244353;
int n, a, b, fac[N], inv[N];
LL k;
inline int C(int x, int y) {
return 1LL * fac[x] * inv[y] % mod * inv[x - y] % mod;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(a), Read(b), Read(k);
fac[0] = fac[1] = inv[0] = inv[1] = 1;
for (int i = 2; i <= n; ++i) {
fac[i] = 1LL * fac[i - 1] * i % mod;
inv[i] = 1LL * (mod - mod / i) * inv[mod % i] % mod;
}
for (int i = 2; i <= n; ++i) {
inv[i] = 1LL * inv[i - 1] * inv[i] % mod;
}
int ans = 0;
for (int i = 0; i <= n && k >= 0; ++i, k -= a) {
if (k % b == 0) {
LL t = k / b;
if (t >= 0 && t <= n) {
ans = (1LL * C(n, i) * C(n, t) + ans) % mod;
}
}
}
printf("%d\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Interval Game
不难发现一定是一左一右地跳,如果往左贡献是 ,往右贡献是 ,贪心即可。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 100005;
int n, l[N], p[N], q[N], r[N];
bool v[N];
inline int Move(int &x, LL &a, int l, int r) {
if (x < l) {
a += l - x, x = l;
} else if (x > r) {
a += x - r, x = r;
}
}
LL Solve() {
for (int i = 1; i <= n; ++i) {
p[i] = q[i] = i, v[i] = false;
}
sort(p + 1, p + n + 1, [&](const int &x, const int &y) {
return l[x] > l[y];
});
sort(q + 1, q + n + 1, [&](const int &x, const int &y) {
return r[x] < r[y];
});
int cur = 0;
LL ret = 0;
for (int t = 1, i = 1, j = 1; t <= n; ++t) {
if (t & 1) {
while (v[p[i]]) {
++i;
}
Move(cur, ret, l[p[i]], r[p[i]]);
v[p[i]] = true;
} else {
while (v[q[j]]) {
++j;
}
Move(cur, ret, l[q[j]], r[q[j]]);
v[q[j]] = true;
}
}
ret += abs(cur);
return ret;
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n);
for (int i = 1; i <= n; ++i) {
Read(l[i]), Read(r[i]);
}
LL ans = Solve();
for (int i = 1; i <= n; ++i) {
l[i] = -l[i], r[i] = -r[i], swap(l[i], r[i]);
}
ans = max(ans, Solve());
printf("%lld\n", ans);
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Choosing Points
如果只考虑一个 的限制,那么矛盾的东西构成了一个二分图,因为只要求保留点数 ,所以每次保留二分图点数较多的那边就可以了。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 605;
int n, p, q, col[N][N], ans[N][N];
vector <pii> trs;
bool vis[N][N];
inline void DFS(int x, int y) {
for (auto e : trs) {
int p = x + e.X, q = y + e.Y;
if (p >= 0 && p < n << 1 && q >= 0 && q < n << 1) {
if (!~col[p][q] && !vis[p][q]) {
col[p][q] = !col[x][y], DFS(p, q);
}
}
}
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(p), Read(q);
trs.clear();
for (int i = 0; i * i <= p; ++i) {
int x = p - i * i, y = sqrt(x);
if (y * y == x) {
trs.pb(mp(i, y));
trs.pb(mp(-i, y));
trs.pb(mp(i, -y));
trs.pb(mp(-i, -y));
}
}
memset(col, -1, sizeof col);
for (int i = 0; i < n << 1; ++i) {
for (int j = 0; j < n << 1; ++j) {
if (!~col[i][j]) {
col[i][j] = 0, DFS(i, j);
}
}
}
int cnt = 0;
for (int i = 0; i < n << 1; ++i) {
for (int j = 0; j < n << 1; ++j) {
if (!col[i][j]) {
++cnt;
}
}
}
if (cnt << 1 < n * n) {
for (int i = 0; i < n << 1; ++i) {
for (int j = 0; j < n << 1; ++j) {
col[i][j] = !col[i][j];
}
}
}
for (int i = 0; i < n << 1; ++i) {
for (int j = 0; j < n << 1; ++j) {
if (col[i][j]) {
vis[i][j] = true;
}
}
}
trs.clear();
for (int i = 0; i * i <= q; ++i) {
int x = q - i * i, y = sqrt(x);
if (y * y == x) {
trs.pb(mp(i, y));
trs.pb(mp(-i, y));
trs.pb(mp(i, -y));
trs.pb(mp(-i, -y));
}
}
memset(col, -1, sizeof col);
for (int i = 0; i < n << 1; ++i) {
for (int j = 0; j < n << 1; ++j) {
if (!~col[i][j] && !vis[i][j]) {
col[i][j] = 0, DFS(i, j);
}
}
}
cnt = 0;
for (int i = 0; i < n << 1; ++i) {
for (int j = 0; j < n << 1; ++j) {
if (!col[i][j] && !vis[i][j]) {
++cnt;
}
}
}
if (cnt < n * n) {
for (int i = 0; i < n << 1; ++i) {
for (int j = 0; j < n << 1; ++j) {
col[i][j] = !col[i][j];
}
}
}
int lim = n * n;
for (int i = 0; i < n << 1; ++i) {
for (int j = 0; j < n << 1; ++j) {
if (!col[i][j] && !vis[i][j]) {
printf("%d %d\n", i, j);
--lim;
if (!lim) {
return 0;
}
}
}
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Walking on a Tree
答案上界是至少被经过一次的边数加上至少被经过两次的边数,可以通过构造证明这个上界。具体地,对 归纳,每次删去一个叶子 ,考虑叶子连出去的边被经过次数,如果是 次或者 次可以不用管它,否则随便取两条路径 和 ,连一条新的路径 ,它们的方向只与 的方向有关。按照这个暴力构造就可以了。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 4005;
int n, m, p, ans, s[N], t[N], deg[N], dep[N], par[N], dis[N][N], vis[N][N];
vector <int> adj[N], pth[N];
bool del[N], ers[N], rev[N];
vector <pii> bel[N];
inline void DFS(int x) {
for (auto y : adj[x]) {
if (y != par[x]) {
par[y] = x, dep[y] = dep[x] + 1, DFS(y);
}
}
}
inline int Dis(int x, int y) {
if (x == y) {
return 0;
}
if (dis[x][y]) {
return dis[x][y];
}
if (dep[x] >= dep[y]) {
return dis[x][y] = Dis(par[x], y) + 1;
} else {
return dis[x][y] = Dis(x, par[y]) + 1;
}
}
inline void Add(int i, int x, int y) {
if (x == y) {
return ;
}
s[i] = x, t[i] = y;
vector <int> l, r;
int u = x, v = y;
while (u != v) {
if (dep[u] >= dep[v]) {
l.pb(u), u = par[u];
} else {
r.pb(v), v = par[v];
}
}
reverse(r.begin(), r.end());
for (auto p : l) {
pth[i].pb(p);
}
pth[i].pb(u);
for (auto p : r) {
pth[i].pb(p);
}
for (int j = 0; j < pth[i].size(); ++j) {
bel[pth[i][j]].pb(mp(i, j));
if (j < pth[i].size() - 1) {
u = pth[i][j], v = pth[i][j + 1];
if (u > v) {
swap(u, v);
}
if (vis[u][v] < 2) {
++vis[u][v], ++ans;
}
}
}
}
inline bool Go(int i, int j, int x) {
return (j < pth[i].size() - 1 && pth[i][j + 1] == x) || (j && pth[i][j - 1] == x);
}
inline int Get(int i, int j, int x) {
return j < pth[i].size() - 1 && pth[i][j + 1] == x ? pth[i].back() : pth[i][0];
}
inline void Make(int i, int x, int y) {
if (rev[i]) {
swap(x, y);
}
if (Dis(s[i], x) + Dis(y, t[i]) + 1 != Dis(s[i], t[i])) {
rev[i] = !rev[i];
}
}
inline void Solve() {
int x = 0;
for (int i = 1; i <= n; ++i) {
if (!ers[i] && deg[i] == 1) {
x = i;
}
}
if (!x) {
return ;
}
int y = 0;
for (auto p : adj[x]) {
if (!ers[p]) {
y = p;
}
}
ers[x] = true, --deg[y];
pii a = mp(0, 0), b = mp(0, 0);
for (auto p : bel[x]) {
if (!del[p.X] && Go(p.X, p.Y, y)) {
if (a.X) {
b = p;
} else {
a = p;
}
}
}
if (!b.X) {
Solve();
} else {
Make(a.X, y, x), Make(b.X, x, y);
Add(++p, Get(a.X, a.Y, y), Get(b.X, b.Y, y));
del[a.X] = del[b.X] = true;
int q = p;
Solve();
rev[a.X] ^= rev[q], rev[b.X] ^= rev[q];
}
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m);
for (int i = 1, x, y; i < n; ++i) {
Read(x), Read(y);
adj[x].pb(y), adj[y].pb(x);
++deg[x], ++deg[y];
}
DFS(1);
for (int i = 1, x, y; i <= m; ++i) {
Read(x), Read(y);
Add(++p, x, y);
}
printf("%d\n", ans);
Solve();
for (int i = 1; i <= m; ++i) {
if (rev[i]) {
printf("%d %d\n", t[i], s[i]);
} else {
printf("%d %d\n", s[i], t[i]);
}
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}
Addition and Andition
从高位到低位一位一位模拟做 遍的过程,碰到 和 直接暴力,不然碰到一段连续的 可以一起做。因为低位的影响不会超过高位,所以不会碰到 。复杂度均摊下来是线性,拿个栈维护一下就行了。
#include <bits/stdc++.h>
using namespace std;
#define X first
#define Y second
#define mp make_pair
#define pb push_back
#define Debug(...) fprintf(stderr, __VA_ARGS__)
typedef long long LL;
typedef long double LD;
typedef unsigned int uint;
typedef pair <int, int> pii;
typedef unsigned long long uLL;
template <typename T> inline void Read(T &x) {
char c = getchar();
bool f = false;
for (x = 0; !isdigit(c); c = getchar()) {
if (c == '-') {
f = true;
}
}
for (; isdigit(c); c = getchar()) {
x = x * 10 + c - '0';
}
if (f) {
x = -x;
}
}
template <typename T> inline bool CheckMax(T &a, const T &b) {
return a < b ? a = b, true : false;
}
template <typename T> inline bool CheckMin(T &a, const T &b) {
return a > b ? a = b, true : false;
}
const int N = 1000005;
const int inf = 0x3f3f3f3f;
stack <pair <int, pii>> cur, tmp;
char s[N], t[N];
int n, m, k;
inline void Push(stack <pair <int, pii>> &s, int x, pii p) {
if (!s.empty() && s.top().Y == p) {
s.top().X += x;
} else {
s.push(mp(x, p));
}
}
inline void Pop(stack <pair <int, pii>> &s, int x) {
if (s.top().X == x) {
s.pop();
} else {
s.top().X -= x;
}
}
int main() {
#ifdef wxh010910
freopen("d.in", "r", stdin);
#endif
Read(n), Read(m), Read(k);
int p = max(n, m);
scanf("%s%s", s + 1, t + 1);
reverse(s + 1, s + n + 1);
reverse(t + 1, t + m + 1);
for (int i = 1; i <= n; ++i) {
s[i] -= '0';
}
for (int i = 1; i <= m; ++i) {
t[i] -= '0';
}
Push(cur, inf, mp(0, 0));
for (int i = p; i; --i) {
if (s[i] && t[i]) {
int z = k;
bool f = true;
while (z) {
int x = cur.top().Y.X, y = cur.top().Y.Y;
if (x) {
Push(tmp, 1, mp(0, 0));
Push(tmp, 1, mp(0, 1));
Pop(cur, 1);
x = cur.top().Y.X, y = cur.top().Y.Y;
if (x) {
Push(tmp, cur.top().X, mp(0, 0));
Pop(cur, cur.top().X);
x = cur.top().Y.X, y = cur.top().Y.Y;
}
Pop(cur, 1);
if (y) {
--z;
} else {
Push(tmp, 1, mp(1, 0));
f = false;
break;
}
} else if (y) {
Push(tmp, 1, mp(0, 0));
Push(tmp, 1, mp(1, 0));
Pop(cur, 1);
x = cur.top().Y.X, y = cur.top().Y.Y;
if (y) {
Push(tmp, cur.top().X, mp(0, 0));
Pop(cur, cur.top().X);
x = cur.top().Y.X, y = cur.top().Y.Y;
}
Pop(cur, 1);
if (x) {
--z;
} else {
Push(tmp, 1, mp(0, 1));
f = false;
break;
}
} else {
int t = min(cur.top().X, z);
Push(tmp, t, mp(0, 0));
Pop(cur, t);
z -= t;
}
}
if (f) {
Push(cur, 1, mp(1, 1));
}
while (!tmp.empty()) {
Push(cur, tmp.top().X, tmp.top().Y);
tmp.pop();
}
} else {
Push(cur, 1, mp(s[i], t[i]));
}
}
vector <pair <int, pii>> v;
while (!cur.empty()) {
v.pb(cur.top()), cur.pop();
}
reverse(v.begin(), v.end());
for (int i = 0; i < v.size(); ++i) {
if (v[i].Y.X) {
for (int j = i; j < v.size(); ++j) {
for (int k = 0; k < v[j].X; ++k) {
putchar(v[j].Y.X + '0');
}
}
putchar(10);
break;
}
}
for (int i = 0; i < v.size(); ++i) {
if (v[i].Y.Y) {
for (int j = i; j < v.size(); ++j) {
for (int k = 0; k < v[j].X; ++k) {
putchar(v[j].Y.Y + '0');
}
}
putchar(10);
break;
}
}
#ifdef wxh010910
Debug("My Time: %.3lfms\n", (double)clock() / CLOCKS_PER_SEC);
#endif
return 0;
}