A. Vika and Her Friends
只需要判断奇偶即可, 核心代码
void solve() {
int n, m, k;
cin >> n >> m >> k;
int x, y;
cin >> x >> y;
int d = (x + y) % 2;
int f = 0;
for (int i = 1; i <= k; i ++) {
cin >> x >> y;
if ((x + y) % 2 == d) f = 1;
}
if (!f) cout << "YES" << endl;
else cout << "NO" << endl;
}
B. Vika and the Bridge
记一下相邻相同数字的最长距离和次长距离, 最优操作可以将最长距离减半,核心代码
void solve() {
int n, k; cin >> n >> k;
vector<int> d(k + 1), cnt(k + 1), d2(k + 1);
vector<int> pre(k + 1);
for (int i = 1; i <= n; i ++) {
int x; cin >> x;
int dd = i - pre[x] - 1;
if (dd > d[x]) d2[x] = d[x], d[x] = dd;
else if (dd > d2[x]) d2[x] = dd;
pre[x] = i;
}
for (int i = 1; i <= k; i ++) {
int dd = n - pre[i];
// if (i == 1) debug(dd)
if (d[i] < dd) d2[i] = d[i], d[i] = dd;
else if (d2[i] < dd) d2[i] = dd;;
}
// for (int i = 1; i <= k; i ++) cout << d2[i] << " ";
// cout <<" sdsd" << endl;
int ans = INF;
for (int i = 1; i <= k; i ++) {
int dd = max(d[i] / 2, d2[i]);
ans = min(ans, dd);
}
cout << ans << endl;
}
C. Vika and Price Tags
相减的操作循环可以全部除去gcd,之后的操作是奇偶循环,判断一下所有周期模三是否相等即可
void solve() {
int n; cin >> n;
vector<int> a(n), b(n), d(n);
for (int i = 0; i < n; i ++) cin >> a[i];
for (int i = 0; i < n; i ++) cin >> b[i];
for (int i = 0; i < n; i ++) {
int gc = gcd(a[i], b[i]);
if (gc != 0) {
a[i] /= gc, b[i] /= gc;
}
if (a[i] == 0 && b[i] == 0) continue;
if (a[i] % 2 == 0) d[i] = 1;
else if (b[i] % 2 == 0) d[i] = 2;
else d[i] = 4;
}
int s = 0;
for (int i = 0; i < n; i ++) {
s |= d[i];
}
if (s == 0 || s == 1 || s == 2 || s == 4) cout << "YES" << endl;
else cout << "NO" << endl;
}
D. Vika and Bonuses
只加最后一位会进入循环,特判一下0,5即可,之后是二次函数求最值
void solve() {
int s, k;
cin >> s >> k;
function<int(int, int)> f = [&](int s, int k) -> int {
if (k == 0) return 0;
int ans = s * k;
if (s % 10 == 0) {
return ans;
}
if (s % 10 != 2) {
ans = max(ans, f(s + s % 10, k - 1));
} else {
// 进入2 4 8 6的循环
int h[5] = {0, 2, 6, 14, 20};
auto g = [&](int n) {
return (s + n / 4 * 20 + h[n % 4]) * (k - n);
};
int m = max((5 * k - s) / 10, 0ll);
for (int i = max(m - 100, 0ll); i <= min(m + 100, k); i ++) {
ans = max(ans, g(i));
}
}
return ans;
};
cout << f(s, k) << endl;
}
E. Vika and Stone Skipping
题意:一个可爱的小女孩lin喜欢打水漂,她打出的水漂每次在水面上飞行的距离成一个等差数列且公差为1,她有一个幸运数字x,她希望计算有多少种等差数列能经过坐标x
题目还给了一个小质数M,处理的时候特别判断一下
void solve() {
int xx, q, M;
map<int, int> mp;
cin >> xx >> q >> M;
xx /= lowbit(xx);
for (int i = 2; i * i <= xx; i ++) {
if (xx % i == 0) {
int cnt = 0;
while (xx % i == 0) {
cnt ++;
xx /= i;
}
mp[i] = cnt;
}
}
if (xx > 1) mp[xx] = 1;
vector<ll> inv(N);
inv[1] = 1;
for (int i = 2; i < N && i < M; i ++) {
inv[i] = M - inv[M % i] * (M / i) % M;
}
ll ans = 1;
int cntM = 0;
auto get_M = [&](int x) {
while (x % M == 0) {
cntM ++;
x /= M;
}
ans *= x % M;
ans %= M;
};
auto get_x = [&](int x) {
while (x % M == 0) {
cntM --;
x /= M;
}
ans *= inv[x % M];
ans %= M;
};
for (auto [x, y] : mp) {
get_M(y + 1);
}
for (int i = 1; i <= q; i ++) {
int x; cin >> x;
x /= lowbit(x);
while (x != 1) {
int p = pr[x], cnt = 0;
while (x % p == 0) {
x /= p;
cnt ++;
}
get_x(mp[p] + 1);
mp[p] += cnt;
get_M(mp[p] + 1);
}
if (cntM > 0) cout << 0 << endl;
else cout << ans << endl;
}
}
F. Vika and Wiki
手玩一下发现一定可以实现,且操作之后会进入周期
void solve() {
int n; cin >> n;
vector<int> a(n);
int ans = 0;
for (auto &x : a) cin >> x;
for (int i = n / 2; i >= 1; i /= 2) {
vector<int> b(n);
for (int j = 0; j < n; j ++) {
b[j] = a[j] ^ a[(j + i) % n];
}
int cnt = 0;
for (int j = 0; j < n; j ++) cnt += b[j] == 0;
if (cnt != n) {
a = b;
ans += i;
}
}
int cnt = 0;
for (int i = 0; i < n; i ++) cnt += a[i] == 0;
ans += cnt != n;
cout << ans << endl;
}