CF1493F Enchanted Matrix
模拟赛碰到的题,来写一发。
关于循环节问题肯定是要找最小循环节,而二维矩形明显能拆成两个一维问题,最后乘起来即可,下面以行为例。
然后考虑循环节一定是 \(n\) 的因子,于是对于一个质因数 \(p\),每次考虑检验前 \(\frac{n}{p^x}\) 个中,按照 \(\frac{n}{p^{x+1}}\) 分成的 \(p\) 块是否相等,不相等时即可知道最小循环节有多少个 \(p\)。
检验的话考虑倍增,每次询问 \([1,2^i]\) 块和 \([2^i+1,2^{i+1}]\) 块是否相等,最后一点单独处理。
总次数为 \(\sum k_i \times \log p_i= \sum \log p_i^{k_i}= \log n\)。
int simons(int a, int b, int c, int d, int e, int f) {
cout << "? " << a << ' ' << b << ' ' << c << ' ' << d << ' ' << e << ' ' << f << endl;
int w;
cin >> w;
return w;
}
int truth(int n, int m) {
auto div = [&](int x) {
vector < pair <int, int> > p;
for (int i = 2; i <= x; i++) {
if (x % i == 0) {
int c = 0;
while (x % i == 0) x /= i, c++;
p.emplace_back(i, c);
}
}
return p;
};
auto p = div(n);
int nres = 1;
for (auto [x, c] : p) {
int lst = n, cc = 0;
for (int i = 1; i <= c; i++) {
int nw = lst / x;
auto chk = [&](int r) -> bool {
int lst = 0;
for (int i = 1; i * 2 <= x; i *= 2) {
if (!simons(i * r, m, 1, 1, i * r + 1, 1)) return 0;
lst = i * 2;
}
lst = x - lst;
if (!lst) return 1;
return simons(lst * r, m, 1, 1, r * x - lst * r + 1, 1);
};
if (!chk(nw)) break;
lst /= x;
cc++;
}
nres *= pow(x, c - cc);
}
p = div(m);
int mres = 1;
for (auto [x, c] : p) {
int lst = m, cc = 0;
for (int i = 1; i <= c; i++) {
int nw = lst / x;
auto chk = [&](int r) -> bool {
int lst = 0;
for (int i = 1; i * 2 <= x; i *= 2) {
if (!simons(n, i * r, 1, 1, 1, i * r + 1)) return 0;
lst = i * 2;
}
lst = x - lst;
if (!lst) return 1;
return simons(n, lst * r, 1, 1, 1, r * x - lst * r + 1);
};
if (!chk(nw)) break;
lst /= x;
cc++;
}
mres *= pow(x, c - cc);
}
nres = n / nres, mres = m / mres;
// debug(nres, mres);
auto cal = [&](int x) {
int cc = 0;
for (int i = 1; i <= x; i++) {
if (x % i == 0) cc++;
}
return cc;
};
return cal(nres) * cal(mres);
}

浙公网安备 33010602011771号