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+mxy
假设 0 0 0距离 ( 1 , 1 ) (1,1) (1,1)的距离为 a a a
显然 a = x + y − 2 a=x+y-2 a=x+y2
联立一下可以得到

a + b = n + m − 2 a+b=n+m-2 a+b=n+m2

n + m − b = x + y n+m-b=x+y n+mb=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;
}
posted @ 2021-10-11 07:57  lahlah  阅读(24)  评论(0编辑  收藏  举报