这个题嘛,怎么说呢
首先你要有一点同余的知识,就可以做惹
o(` • ~ • ′。)o
因为题中保证了
gcd(n,dx)==1和gcd(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;
}