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);
}
posted @ 2024-10-06 00:51  Anonymely  阅读(20)  评论(0)    收藏  举报