Y
K
N
U
F

复杂度证明比题难:题解:P12522 [Aboi Round 1] 限りなく灰色へ

[Aboi Round 1] 限りなく灰色へ

阿巴阿巴,我是不是有什么奇奇怪怪的执念之类的东西啊。

之前是因为根号分治把我骗进来的,现在终于补习了莫反,做一下。

我怎么没有是人认证。

正文

首先是一个一个,线段上没有其他整点可以转化为 \(\gcd (|x-x_i|,|y-y_i|) = 1\)。那么就会有一个显然的 \(\mathcal O(XYn\log X)\) 的做法,直接枚举,可以有整整 \(20\) 分拿。

然后考虑把柿子写出来。

\[\max_{x=1}^X\max_{y=1}^Y \sum_{i=1}^{n} [\gcd(|x-x_i|,|y-y_i|)] \]

显然化成。

\[\max_{x=1}^X\max_{y=1}^Y\sum_{i=1}^{n} \sum_{d|\gcd(|x-x_i|,|y-y_i|)} \mu(d) \]

改成枚举 \(d\)\(V\) 为值域。

\[\max_{x=1}^X\max_{y=1}^Y \sum_{d}^{V} \mu(d)\sum_{i=1}^{n} [d|\gcd(|x-x_i|,|y-y_i|)] \]

\(\gcd\) 拆开。

\[\max_{x=1}^X\max_{y=1}^Y \sum_{d}^{V} \mu(d)\sum_{i=1}^{n} [d||x-x_i|] [d||y-y_i|] \]

再把整除拆开。

\[\max_{x=1}^X\max_{y=1}^Y \sum_{d}^{V} \mu(d)\sum_{i=1}^{n} [x\equiv x_i\pmod d] [y\equiv y_i\pmod d] \]

发现可以对 \(d\) 分治,\(d\) 小则预处理 \(x_i,y_i\mod d\) 的值,\(d\) 大则暴力枚举,然后就感性认知这似乎是 \(60\) 分的做法。

但是,为什么不试着交一下呢?

AC 了。

考虑证明复杂度。

复杂度证明

不会证,算了。

考虑到不证不给过审,证明一下。

设分治边界是 \(B\)

显然前一部分是 \(\mathcal O(n^2B)\) 的,不提。

考虑另一部分,列出来是 \(\mathcal O(n^3 \sum _{d=B}^n \frac 1{d^2})\)

\[\begin{aligned}\sum_{d=B}^n \frac 1{d^2} &= \sum_{d=1}^n \frac 1{d^2}- \sum_{d=1}^{B-1} \frac 1{d^2} \\&\approx (\frac {\pi ^2}{6} - \frac 1n) - (\frac {\pi ^2}{6} - \frac 1{B-1}) \\&= \frac 1{B-1} - \frac 1n\\ &\approx \frac 1{B}\end{aligned} \]

容易发现 \(B\) 取到 \(\sqrt n\) 最优,有时间复杂度 \(\mathcal O(n^2\sqrt n)\)

讲个笑话,我最后这里没加句号又打回一次。

code

// code by 樓影沫瞬_Hz17
#include <bits/extc++.h>

using namespace std;
 
constexpr int N = 2010, B = 37;

int X, Y, x[N], y[N], n;

int u[N], p[N], cnp;
int vis[N];

inline void line(int n) {
	u[1] = 1;
	for(int i = 2; i <= n; i ++) {
		if(!vis[i]) {
			p[++ cnp] = i;
			u[i] = -1;
		}
		for(int j = 1; j <= cnp and p[j] * i <= n; j ++) {
			vis[p[j] * i] = 1;
			if(i % p[j] == 0) {
				u[i * p[j]] = 0;
				break;
			}
			u[i * p[j]] = -u[i];
		}
	}
}

int me[N][N];

int sz[100][100][100];

int ans[N][N];

int su[N];

signed main() {
	#ifndef ONLINE_JUDGE
        freopen("in.ru", "r", stdin);
        freopen("out.ru", "w", stdout);
    #endif
	ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);

	cin >> X >> Y >> n;

	for(int i = 1; i <= n; i ++) cin >> x[i] >> y[i], me[x[i]][y[i]] ++;

	line(2000);

	int csu = 0;
	for(int i = 1; i <= 2000; i ++) if(u[i] != 0) su[++ csu] = i;

	for(int j = 1; j <= B; j ++) {
		int d = su[j];
		for(int i = 1; i <= n; i ++) sz[j][x[i] % d][y[i] % d] ++;
	}

	for(int j = 1; j <= B; j ++) {
		int d = su[j];
		for(int x = 1; x <= X; x ++) 
			for(int y = 1; y <= Y; y ++) 
				ans[x][y] += (sz[j][x % d][y % d] - me[x][y]) * u[d];
	}

	for(int j = B + 1; j <= csu; j ++) {
		int d = su[j];
		for(int i = 1; i <= n; i ++) {
			for(int xt = x[i] % d; xt <= X; xt += d) {
				for(int yt = y[i] % d; yt <= Y; yt += d) {
					if(xt == x[i] and yt == y[i]) continue;
					ans[xt][yt] += u[d];
				}
			}
		}
	}

	for(int i = 1; i <= n; i ++) ans[x[i]][y[i]] ++;

	int as = -1;

	for(int i = 1; i <= X; i ++) 
		for(int j = 1; j <= Y; j ++) 
			as = max(as, ans[i][j]);	

	cout << as << '\n';
}
我怎么没有是人认证。
posted @ 2025-11-24 17:37  樓影沫瞬_Hz17  阅读(5)  评论(0)    收藏  举报