CF1493F Enchanted Matrix

Anonymely發表於2024-10-06

模擬賽碰到的題,來寫一發。

關於迴圈節問題肯定是要找最小迴圈節,而二維矩形明顯能拆成兩個一維問題,最後乘起來即可,下面以行為例。

然後考慮迴圈節一定是 \(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);
}

相關文章