T1. 反转
枚举反转了多少行和列(因为行和行之间本身没有区别,列同理),算一下是否有 \(k\) 个格子被反转。
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
void solve() {
int n, m, k;
cin >> n >> m >> k;
rep(i, n+1) {
rep(j, m+1) {
if (i*j + (n-i)*(m-j) == k) {
puts("Yes");
return;
}
}
}
puts("No");
}
int main() {
int t;
cin >> t;
while (t--) solve();
return 0;
}
T2. 函数
请注意,该序列是循环的,意味着序列的形式如下:
我们几乎可以通过确定循环节来完成整个任务。循环节个数是 \(3\) 个整数组成的段数。区间长度是 \(r-l+1\),因此循环节个数为 \(\lfloor\frac{r-l+1}{3}\rfloor\) 。
我们通过注意到循环从区间第一个 \(a\) 开始,最后一个 \(a \oplus b\) 结束,来获取循环开始和结束下标。除此之外,我们再来求剩余的元素(最多 \(2\) 个)的和,循环部分的和为:
总复杂度为 \(O(n)\)
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
void solve() {
int a, b, l, r;
cin >> a >> b >> l >> r;
--l; --r;
vector<int> x(3);
x[0] = a;
x[1] = b;
x[2] = a^b;
ll sum = 0;
rep(i, 3) sum += x[i];
int n = r-l+1;
int si = l%3;
ll ans = n/3*sum;
n %= 3;
rep(i, n) ans += x[(si+i)%3];
cout << ans << '\n';
}
int main() {
int t;
cin >> t;
while (t--) solve();
return 0;
}
T3. 电管
显然红蓝绿对应 \(0 \sim 2\) 三种数。考虑构造一种运算符,发现 \(a \oplus b = -(a+b)\) 是合理的。
然后考虑 \(a_i\) 对 \(a_{i-d}\) 的贡献。注意到构造的运算符对 \(a_i\) 的贡献大概长 \(a_i = -(a_i + a_{i+1})\),说明按一次开关,\(a_i\) 会对 \(a_{i-1}\) 和 \(a_i\) 造成一次贡献。推广到按下 \(m\) 次开关的情况,其中 \(a_i\) 对 \(a_{i-d}\) 的贡献为 \(\binom{m}{d}\) 。注意到我们最终的答案要对 \(3\) 取模,考虑 \(\text{Lucas}\) 定理。
注意到一个现实意义是,我们按 \(a+b\) 次,和先按 \(a\) 次,再按 \(b\) 次的结果是一样的,我们考虑将 \(m\) 三进制分解,每次只取出一个 \(3^x\),这样 \(d\) 只有为 \(0\) 或 \(3^x\) 时,才会产生贡献,且系数为 \(1\) 。可以直接暴力做,时间复杂度为 \(O(n\log m)\) 。
代码实现
#include <bits/stdc++.h>
#define rep(i, n) for (int i = 0; i < (n); ++i)
using namespace std;
using ll = long long;
int main() {
int n; ll m;
string s;
cin >> n >> m >> s;
vector<int> a(n);
rep(i, n) {
if (s[i] == 'r') a[i] = 0;
if (s[i] == 'g') a[i] = 1;
if (s[i] == 'b') a[i] = 2;
}
ll x = m;
ll t = 1;
while (x) {
for (int ri = 1; ri <= x%3; ++ri) {
vector<int> b(n);
rep(i, n) b[i] = (a[i]+a[(i+t)%n])%3;
rep(i, n) a[i] = b[i];
}
t *= 3;
x /= 3;
}
if (m&1) {
rep(i, n) a[i] = (3-a[i])%3;
}
string ans;
rep(i, n) {
if (a[i] == 0) ans += 'r';
if (a[i] == 1) ans += 'g';
if (a[i] == 2) ans += 'b';
}
cout << ans << '\n';
return 0;
}
T4. 柚子
原题:惊蛰
浙公网安备 33010602011771号