Codeforces Round #615 (Div. 3)
Codeforces Round #615 (Div.3)
A
思路
假设 \(a \leq b \leq c\) ,使三人钱币数相等首先要满足 \(x \geq c - a + c - b\) ,其次要满足剩余量是 \(3\) 的整数倍。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e5+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
fac[0] = 1;
for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
inv[maxn-1] = ksm(fac[maxn-1], mod-2);
for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int T, n, m;
int a[5];
int main() {
scanf("%d", &T);
while (T--) {
for (int i = 1; i <= 3; ++i) scanf("%d", a+i);
scanf("%d", &n);
sort(a + 1, a + 1 + 3);
ll need = 2ll * a[3] - a[2] - a[1];
if (need <= n && (n - need) % 3 == 0) puts("YES");
else puts("NO");
}
return 0;
}
B
思路
显然,\(R\) 的字典序小于 \(U\) ,所以在保证能走完全部点的前提下,先往右走再往上走。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 1e5+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
fac[0] = 1;
for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
inv[maxn-1] = ksm(fac[maxn-1], mod-2);
for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
struct node {
int x, y;
inline void read() { scanf("%d%d", &x, &y); }
inline bool operator < (const node &phs) const { return x == phs.x? y < phs.y: x < phs.x; }
}a[maxn];
int T, n, m;
void solve() {
scanf("%d", &n);
for (int i = 1; i <= n; ++i)
a[i].read();
sort(a + 1, a + 1 + n);
bool fg = false;
int x = 0, y = 0;
string str = "";
for (int i = 1; i <= n; ++i) {
if (a[i].x >= x && a[i].y >= y) {
for (int j = x + 1; j <= a[i].x; ++j) str.push_back('R');
for (int j = y + 1; j <= a[i].y; ++j) str.push_back('U');
x = a[i].x, y = a[i].y;
} else {
fg = 1;
break;
}
}
if (fg) puts("NO");
else {
puts("YES");
cout << str << endl;
}
}
int main() {
scanf("%d", &T);
while (T--)
solve();
return 0;
}
C
思路
只要 \(n\) 的质因子重组成三个不同数即可。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 3e6+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
const int inf = 1e9;
int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
fac[0] = 1;
for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
inv[maxn-1] = ksm(fac[maxn-1], mod-2);
for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int prime[maxn], pn;
bool nt[maxn];
void prePrime() {
for (int i = 2; i < maxn; ++i) {
if (!nt[i]) prime[pn++] = i;
for (int j = 0; j < pn && prime[j] * i < maxn; ++j) {
nt[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
struct node {
int x, y;
inline void read() { scanf("%d%d", &x, &y); }
inline bool operator < (const node &phs) const { return x == phs.x? y < phs.y: x < phs.x; }
}a[maxn];
int T, n, m;
const int block = sqrt(inf);
void solve() {
scanf("%d", &n);
vector<int> q;
for (int i = 0; i < pn && prime[i] <= n; ++i) {
while(n % prime[i] == 0) {
n /= prime[i];
q.push_back(prime[i]);
}
}
if(n > 1) q.push_back(n);
int sz = q.size();
if(sz < 3) puts("NO") ;
else {
int ans[5] = {1, 1, 1, 1, 1};
int j = 0;
for (int i = 1; i <= 3; ++i) {
if (j < sz) ans[i] = q[j++];
while(ans[i] == ans[i-1] && j < sz) ans[i] *= q[j++];
}
while(j < sz) ans[3] *= q[j++];
sort(ans + 1, ans + 1 + 3);
bool fg = false;
for (int i = 1; i <= 3; ++i) {
if(ans[i] == ans[i-1] || ans[i] < 2) {
fg = 1;
break;
}
}
if(fg) puts("NO");
else {
puts("YES");
printf("%d %d %d\n", ans[1], ans[2], ans[3]);
}
}
}
int main() {
prePrime();
scanf("%d", &T);
while (T--)
solve();
return 0;
}
D
思路
简单分析后,发现这是个 \(m\) 的剩余系,所以,每次 query 的答案模 \(m\) 的结果为即为 \(0 \sim m-1\) 中出现次数最少的那个。
我们随便用线段树维护一下即可。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 3e6+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
const int inf = 1e9;
int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
fac[0] = 1;
for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
inv[maxn-1] = ksm(fac[maxn-1], mod-2);
for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int prime[maxn], pn;
bool nt[maxn];
void prePrime() {
for (int i = 2; i < maxn; ++i) {
if (!nt[i]) prime[pn++] = i;
for (int j = 0; j < pn && prime[j] * i < maxn; ++j) {
nt[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
int T, n, m;
struct node {
int l, r, val, pos;
}tr[maxn<<2];
#define ls i<<1
#define rs i<<1|1
void pushup(int i) {
if(tr[ls].val > tr[rs].val) {
tr[i].val = tr[rs].val;
tr[i].pos = tr[rs].pos;
} else {
tr[i].val = tr[ls].val;
tr[i].pos = tr[ls].pos;
}
}
void build(int l, int r, int i) {
tr[i] = node{l, r, inf, inf};
if(l == r) { tr[i].val = 0, tr[i].pos = l; return; }
int mid = l + r >> 1;
build(l, mid, ls); build(mid+1, r, rs);
pushup(i);
}
void update(int pos, int i) {
if(tr[i]. l == tr[i].r) {
++tr[i].val;
return;
}
int mid = tr[i].l + tr[i].r >> 1;
if(pos <= mid) update(pos, ls);
else update(pos, rs);
pushup(i);
}
void solve() {
scanf("%d%d", &n, &m);
build(1, m, 1);
for (int x, i = 1; i <= n; ++i) {
scanf("%d", &x);
x %= m; ++x;
update(x, 1);
printf("%d\n", tr[1].pos-1 + m * tr[1].val);
}
}
int main() {
solve();
return 0;
}
E
思路
题目中有两种操作:
一、将任意一个数更改为另一个数。
二、将某一列循环向上拨动一个位置。
所以我们可以每一列拆开处理。
对于每一列中的每个数,我们记录一下这个数是否应为这一列的数字,若不是则pass,若是则统计假如将他拨动到对应位置的第一行现在在第几行即可。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 2e5+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
const int inf = 1e9;
int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
fac[0] = 1;
for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
inv[maxn-1] = ksm(fac[maxn-1], mod-2);
for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int prime[maxn], pn;
bool nt[maxn];
void prePrime() {
for (int i = 2; i < maxn; ++i) {
if (!nt[i]) prime[pn++] = i;
for (int j = 0; j < pn && prime[j] * i < maxn; ++j) {
nt[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
int T, n, m;
int cnt[maxn];
vector<int> vec[maxn];
void solve() {
scanf("%d%d", &n, &m);
ll res = 0;
for (int i = 1; i <= n; ++i) for (int x, j = 1; j <= m; ++j) scanf("%d", &x), vec[j].push_back(x);
for (int i = 1; i <= m; ++i) {
for (int j = 1; j <= n; ++j) cnt[j] = 0;
for (int j = 1; j <= n; ++j) {
int x = vec[i][j-1];
if (x % m == i % m && x <= n*m) {
int pos = j - (x +m-1)/ m + 1;
if (pos <= 0) pos += n;
++cnt[pos];
}
}
int sum = inf;
for (int j = 1; j <= n; ++j) sum = min(sum, j - 1 + n - cnt[j]);
res += sum;
}
printf("%lld\n", res);
}
int main() {
solve();
return 0;
}
F
思路
抽象后的题意即为从该树找到三个节点,若他们的 \(lca\) 为 \(x\) ,使得这三个点到 \(x\) 点的边的并集的数量最大。
首先可以固定三个点中的两个点分别是树直径的两个端点,剩余的一个点则为到直径距离最远的一个点。
Code
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int, int> pii;
const int maxn = 3e6+10;
const int mod = 1e9+7;
const int maxm = 1e3+10;
const int inf = 1e9;
int tree[maxn];
inline int lowbit(int x) { return x & -x; }
inline void modify(int x, int val) { for (int i = x; i < maxn; i += lowbit(i)) tree[i] += val; }
inline int query (int x) { int res = 0; for (int i = x; i ; i -= lowbit(i)) res += tree[i]; return res; }
ll ksm(ll a, ll n) { ll res = 1; while (n) { if (n & 1) res = res * a % mod; a = a * a % mod; n >>= 1; } return res; }
ll fac[maxn], inv[maxn];
void facInit() {
fac[0] = 1;
for (int i = 1; i < maxn; ++i) fac[i] = fac[i-1] * i % mod;
inv[maxn-1] = ksm(fac[maxn-1], mod-2);
for (int i = maxn-2; i >= 0; --i) inv[i] = inv[i+1] * (i+1) % mod;
}
ll C(int n, int m) { return fac[n] * inv[m] % mod * inv[n-m] % mod; }
int prime[maxn], pn;
bool nt[maxn];
void prePrime() {
for (int i = 2; i < maxn; ++i) {
if (!nt[i]) prime[pn++] = i;
for (int j = 0; j < pn && prime[j] * i < maxn; ++j) {
nt[i * prime[j]] = 1;
if (i % prime[j] == 0) break;
}
}
}
int n;
vector<int> g[maxn];
bool vis[maxn];
int f[maxn], dep[maxn];
void dfs(int x, int fa = 0) {
f[x] = fa;
if(vis[x]) dep[x] = 1;
else dep[x] = dep[fa] + 1;
for (auto v: g[x]) {
if (v == fa) continue;
dfs(v, x);
}
}
void solve() {
scanf("%d", &n);
for (int u, v, i = 1; i < n; ++i) {
scanf("%d%d", &u, &v);
g[u].push_back(v);
g[v].push_back(u);
}
int a = 0, b = 0, c = 0, ans = 0;
dfs(1);
for (int i = 1; i <= n; ++i) if (dep[i] > dep[a]) a = i;
dfs(a);
for (int i = 1; i <= n; ++i) if (dep[i] > dep[b] && i != a) b = i;
int p = b;
while(p) {
vis[p] = 1;
p = f[p];
++ans;
}
--ans;
dfs(a);
for (int i = 1; i <= n; ++i) if (dep[i] > dep[c] && i != a && i != b) c = i;
p = c;
while(p) {
if (vis[p]) break;
++ans;
p = f[p];
}
printf("%d\n%d %d %d\n", ans, a, b, c);
}
int main() {
solve();
return 0;
}