CodeForces #280 E Vanya and Field

这个题嘛,怎么说呢

首先你要有一点同余的知识,就可以做惹
o(` • ~ • ′。)o

因为题中保证了 gcd(n,dx)==1gcd(n,dy)==1
这保证了根据题目中的走法//从 (x,y) 走到 ((x+dx)modn,(y+dy)modn)

在从起点开始走n步之后,一定能回到起点!

这个是个很神奇的性质(并没有

也就是说,我们通过互相可达这个关系(如果你有兴趣的话,可以证明这个关系是一个等价关系),将这个 n×n 的网格,分成了一些等价类
那么会有几个等价类呢?
简单的考虑每一个等价类中的格子的数目(其实也就是刚才说的从起点开始走n步能回到起点)正好是n个
也就是说我们有 n×nn=n 个等价类
( 这特喵不是废话吗(╯‵□′)╯︵┻━┻
然后问题就转化为了如何找到那个包含苹果最多的等价类
╮(╯_╰)╭好像问题还是毫无进展啊
自然的,我们选择其中的任意一行(一般在不知道该怎么接下去的时候,我们都会说一句这是自然的(笑)
或许你会发现这一行的每一个格子都分属于不同的等价类
限于篇幅关系,我就不证明了(其实是我也不知道怎么证……
然后我们要做的对于每一个有苹果的格子,计算出和它同属一个等价类的第一行(如果你任性,任何一行任何一列都是可以的╮( ̄▽ ̄”)╭ ),这一步可以用扩展欧几里得算法去做,给那个格子上的苹果树标记+1
接下来我想大家应该都会了,直接上代码吧

const int maxn = 1123456;
#define LL long long
int arr[maxn];

LL extendGCD(LL a, LL b, LL& x, LL& y) {
    if(!b){
        return x = 1, y = 0, a;
    }
    LL res = extendGCD(b, a % b, x, y), tmp = x;
    x = y, y = tmp - (a / b) * y;
    return res;
}

int main(){
    int n,m;
    scanf("%d %d",&n,&m);
    memset(arr,0,sizeof(arr));
    LL dx,dy;
    scanf("%I64d %I64d",&dx,&dy);
    LL x,y;
    LL a,b;
    extendGCD(dx,n,a,b);
    a = (a+n)%n;
    while(m--){
        scanf("%I64d %I64d",&x,&y);
        LL p = n-(a*x)%n;
        int t = (y+dy*p)%n;
        arr[t]++;
    }
    int t = max_element(arr,arr+n)-arr;
    printf("%d %d\n",0,t);
    return 0;
}

你可能感兴趣的:(CodeForces #280 E Vanya and Field)