【洛谷】【LGR-167-Div.2】复旦勰码 12 月月赛 I 做题记录
A. 「RiOI-03」water problem
比赛一开始犯蠢了,直接考虑打表,不过需要注意的是除了把一个分成若干个小正方形的这个分法以外,还有一种分法是可以让满足 \(n\geq 4\) 且 \(n \equiv 0(\mod 2)\) 满足条件。
最后得到的结论就是 \(2,3,5\) 是不可以的,其余都是可以的。
B. 「RiOI-03」匀速相遇
根据关系速度关系列出方程,可以发现如果两个点要能够相遇,必须要满足:
\[a[i]\times i=b[j] \times j
\]
特判一下 0,然后用 umap 存储一下就可以了。
C. 「RiOI-03」3-2
可以很容易得到一个结论就是答案一定是 \(2^k-1\) 的形式。
再观察一下 \(n = 3\) 的形式,那么就可以找到规律其实就找到当前联通块最长的某个横行,然后 \(k\) 就等于这个横行的长度。
并且这个横行既可以在联通块的最上方也可以在最下方,所以取往上找和往下找的最大值即可。
#include <bits/stdc++.h>
using namespace std;
using i64 = long long;
const int P = 998244353;
int power(int x, i64 y) {
int r = 1;
for (; y; y /= 2, x = 1ll * x * x % P) {
if (y & 1) r = 1ll * r * x % P;
}
return r;
}
int main() {
ios::sync_with_stdio(false), cin.tie(nullptr), cout.tie(nullptr);
i64 n;
int q;
cin >> n >> q;
while (q--) {
i64 x, y;
cin >> x >> y;
if (y >= 60) {
int ans = power(2, n) - 1;
if (ans < 0) {
ans += P;
}
cout << ans << "\n";
} else {
int up = min(n, 60ll);
auto count = [&](i64 x) {
int cnt = 0;
for (int i = y; i >= 0; i--) {
if ((x >> i & 1) == (x >> y & 1)) cnt++;
else break;
}
for (int i = y + 1; i < up; i++) {
if ((x >> i & 1) == (x >> y & 1)) cnt++;
else break;
}
return cnt;
};
int mx = 0;
{
i64 val = x;
for (int i = y; i >= 0; i--) {
if ((val >> y & 1) == ((val + (1ll << i)) >> y & 1)) {
val += 1ll << i;
}
}
mx = max(mx, count(val));
}
{
i64 val = x;
for (int i = y; i >= 0; i--) {
if (val >= (1ll << i) && (val >> y & 1) == ((val - (1ll << i)) >> y & 1)) {
val -= 1ll << i;
}
}
mx = max(mx, count(val));
}
int ans = power(2, mx) - 1;
if (ans < 0) ans += P;
cout << ans << "\n";
}
}
}
D. 「RiOI-03」Just a Q. (Easy ver.)
待补
E. 「RiOI-03」网格
待补

浙公网安备 33010602011771号