Vanya and Field

Vanya and Field

题目链接:http://www.codeforces.com/problemset/problem/492/E

逆元

刚看到这题的时候一脸懵逼不知道从哪下手好,于是打表找规律。但是打出来的东西完全不能看啊,有个鬼规律(╯‵□′)╯︵┻━┻,是我数据处理不当?按x排序后发现从一个点出发可以到达任意一个x坐标,回过去看题,发现有这么一句话:The following condition is satisfied for the vector:$gcd(n,dx)=gcd(n,dy)=1$,恩,好像有点思路了。(x,y)的下一个点的坐标是[(x+k*dx)%n,(y+k*dy)%n]也可以写作[(x+k*dx+a*n),(y+k*dy+b*n)],也就是说每个不互相覆盖的(x,y)都唯一对应一个(0,y'),利用扩展欧几里得(如果n是质数可以用费马小定理)计算dx对n的逆元,从而可以求得对应的y'。于是只要处理每个(x,y),对应的(0,y')个数++,最后找到个数最多的(0,y')就好了。

代码如下:

 1 #include<cstdio>
 2 #define LL long long
 3 using namespace std;
 4 LL k,t;
 5 struct node{
 6     LL sum,x,y;
 7     bool flag;
 8 }times[1000005];
 9 LL query[100005][2];
10 LL n,m,dx,dy;
11 LL exGCD(LL a,LL b){
12     if(b==0){
13         k=1;
14         t=0;
15         return a;
16     }
17     LL r=exGCD(b,a%b);
18     LL tmp=k;
19     k=t;
20     t=tmp-(a/b)*t;
21     return r;
22 }
23 int main(void){
24     LL Max=0,Index=0;
25     scanf("%I64d%I64d%I64d%I64d",&n,&m,&dx,&dy);
26     exGCD(dx,n);
27     k=(k%n+n)%n;
28     for(LL i=0;i<m;++i){
29         LL x,y;
30         scanf("%I64d%I64d",&x,&y);
31         query[i][0]=x,query[i][1]=y;
32         LL temp=y-x*k*dy;
33         temp = (temp%n + n)%n;
34         temp%=n;
35         times[temp].sum++;
36         if(times[temp].sum>Max){
37             Max=times[temp].sum;
38             Index=temp;
39         }
40         if(times[temp].flag==0){
41             times[temp].x=x;
42             times[temp].y=y;
43             times[temp].flag=1;
44         }
45     }
46     printf("%I64d %I64d
",times[Index].x,times[Index].y);
47     return 0;
48 }
原文地址:https://www.cnblogs.com/barrier/p/5769649.html