题意:有长度为n的环,环上有m个坏点,目标在z位置,从1出发,每次跳k步,最后到达z,问最小的k是多少。

题解:1、暴力枚举,我没试过,但有人这样过了。

   2、考虑目标z,假设跳了m圈,最后跳到z,则有(z-1+m*n)≡0 (mod k),如果(z-1)%k==0,直接检验小于z的坏点是否会猜到,否则,m*n≡(z-1)%k (mod k),用模线性方程可以求出m,考虑坏点,分为两类,一类坏点的坐标小于z,人会从上面跨过m+1次,另一类坏点坐标大于z,人会从上面跨过m次。

     对于任意一个坏点a,如果在某一次踩在了它上面,就存在(a-1)*(a-1+n)*(a-1+2*n)*(a-1+3*n)....(a-1+m*n)≡0 (mod k),反之,就是存在a-1+k*n≡0 (mod k),可以用上面方法求出k,如果坏点属于第一类,则k必须大于m,否则k大于等于m,然后枚举k在依次验证。

  

View Code
 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 using namespace std;
 5 inline int gcd(int a,int b)
 6 {
 7     if(b==0)
 8         return a;
 9     else
10         return gcd(b,a%b);
11 }
12 inline int extgcd(int a,int b,int &x,int &y)
13 {
14     if (b==0)
15     {
16         x=1,y=0;
17         return a;
18     }
19     int d, tp;
20     d=extgcd (b, a%b, x, y);
21     tp=x;
22     x=y;
23     y=tp - a/b*y;
24     return d;
25 }
26 inline int getx(int a, int b, int n) // ! n > 0
27 {
28     int e, i, d, x, y;
29     d = extgcd(a, n, x, y);
30     if (b%d>0) return -1;
31     else
32     {
33         e=(x*(b/d))%n;
34         int ans=e,t=n/d,num=(n-e)/t;
35         for(i=-1;i<=1;i++)
36             e=(e+(num+i)*t+n)%n,ans=min(ans,e);
37         return ans;
38     }
39 }
40 int s1[1005],s2[1005],top1,top2;
41 int main()
42 {
43     int n,z,m;
44     while(scanf("%d%d%d",&n,&z,&m)!=EOF)
45     {
46         int i,k,v;
47         top1=top2=0;
48         for(int i=0; i<m; i++)
49         {
50             scanf("%d",&v);
51             if(v<z)
52                 s1[top1++]=v;
53             else
54                 s2[top2++]=v;
55         }
56         if(top1==0)
57         {
58             printf("1\n");
59             continue;
60         }
61         for(k=2; k<z; k++)
62         {
63             int b,d=gcd(k,z-1);
64             if(d==k)
65             {
66                 for(i=0; i<top1; i++)
67                     if((s1[i]-1)%k==0)
68                         break;
69                 if(i<top1)
70                     continue;
71                 printf("%d\n",k);
72                 break;
73             }
74             m=getx(n,k-(z-1)%k,k);
75             if(m==-1)
76                 continue;
77             for(i=0; i<top1; i++)
78                 if((s1[i]-1)%k==0||((v=getx(n,k-(s1[i]-1)%k,k))!=-1&&v<=m))
79                     break;
80             if(i<top1)
81                 continue;
82             for(i=0; i<top2; i++)
83                 if((s2[i]-1)%k==0||((v=getx(n,k-(s2[i]-1)%k,k))!=-1&&v<m))
84                     break;
85             if(i<top2)
86                 continue;
87             printf("%d\n",k);
88             break;
89         }
90     }
91     return 0;
92 }