CF1004D Sonya and Matrix
https://www.luogu.com.cn/problem/CF1004D
分析题
首先可以通过镜像和旋转使得0在第二象限(左上方)
也可以发现距离 0 ( x , y ) 0(x,y) 0(x,y)最远的 ( n , m ) (n,m) (n,m)就是给出的最大值,假设为 b b b
即
b
=
n
+
m
−
x
−
y
b=n+m-x-y
b=n+m−x−y
假设
0
0
0距离
(
1
,
1
)
(1,1)
(1,1)的距离为
a
a
a
显然
a
=
x
+
y
−
2
a=x+y-2
a=x+y−2
联立一下可以得到
a + b = n + m − 2 a+b=n+m-2 a+b=n+m−2
n
+
m
−
b
=
x
+
y
n+m-b=x+y
n+m−b=x+y
对于这条式子
b
b
b是已知的,
n
,
m
n,m
n,m可以低复杂度枚举
现在考虑怎么搞出
(
x
,
y
)
(x,y)
(x,y)中的其中一个
那么怎么求
x
x
x呢?
到
0
0
0距离为
d
d
d的点一定有
4
d
4d
4d个
所以可以枚举这个d,第一个不满足的
d
d
d就是
x
x
x
可以参考代码理解
code:
#include<bits/stdc++.h>
#define N 2000050
using namespace std;
int gs[N], cnt[N], t;
int check() {
for(int i = 1; i <= t; i ++) if(gs[i] != cnt[i]) return 0;
return 1;
}
int main() {
scanf("%d", &t);
int b = 0;
for(int i = 1; i <= t; i ++) {
int x;
scanf("%d", &x); cnt[x] ++;
b = max(b, x);
}
int x = 0, y = 0;
for(int i = 1; i <= t; i ++)
if(cnt[i] < i * 4) {x = i; break;}
for(int n = x; n <= t; n ++) if(t % n == 0) {
int m = t / n, y = n + m - b - x;
if(abs(n - x) + abs(m - y) == b) {
memset(gs, 0, sizeof gs);
for(int i = 1; i <= n; i ++)
for(int j = 1; j <= m; j ++)
gs[abs(i - x) + abs(j - y)] ++;
if(check()) {
printf("%d %d\n%d %d", n, m, x, y);
return 0;
}
}
}
puts("-1");
return 0;
}