Preface
为啥有蓝啊,这题在机房里 15min 左右就切了,反倒是 2A 做了 1h。。
Solution
将矩阵逆时针旋转 \(90^{\circ}\),你会发现这是一棵线段树,是父亲左儿子的节点颜色是 \(0\),是右儿子的节点颜色是 \(1\)。
容易发现,联通块一定是一条链。具体地,你从给定的点向上跳,跳到第一个与自己异色的点,然后从这个点一路向下联通,可以联通到叶子。
我们令叶子那层是第 \(0\) 层,那么如果向上跳到的点深度为 \(d\),答案就是 \(\sum_{i=0}^{d}2^i=2^{d+1}-1\)。
判断 \(y\) 是否超出了 \(x\) 的最高位,如果是,说明能联通到根,答案为 \(2^n-1\);否则暴力向上跳即可。
时间复杂度 \(\mathcal{O}(q\log n)\)。
Code
#include <bits/stdc++.h>
#define REP(i, l, r) for (int i = (l); i <= (r); ++ i)
#define DEP(i, r, l) for (int i = (r); i >= (l); -- i)
#define fi first
#define se second
#define pb push_back
using namespace std;
namespace Milkcat {
typedef long long LL;
typedef pair<LL, LL> pii;
const int N = 1e6 + 5, mod = 998244353;
LL n, q, x, y;
LL qpow(LL b, LL k) { LL r = 1; for (; k; b = b * b % mod, k >>= 1) if (k & 1) r = r * b % mod; return r; }
int main() {
cin >> n >> q;
REP(test, 1, q) {
cin >> x >> y;
if (__lg(x) < y) {
cout << (qpow(2, n) - 1 + mod) % mod << '\n';
} else {
int p = x >> y & 1;
while ((x >> y & 1) == p) y ++;
cout << (qpow(2, y) - 1 + mod) % mod << '\n';
}
}
return 0;
}
}
int main() {
ios::sync_with_stdio(0);
cin.tie(0), cout.tie(0);
int T = 1;
while (T --) Milkcat::main();
return 0;
}
标签:03,联通,int,题解,LL,mod,RiOI,define
From: https://www.cnblogs.com/Milkcatqwq/p/17975408