D题的妙妙解法:

时间复杂度

思路:

我这里的点是从

因为 走两次及以上没有意义(走回来了),将 分两种:

  1. 答案为从 走到 (等价于从 )。

  2. 答案取

    上面的值

    走到 (等价于从 )加上一

    最小的那个。

我们记录用 能走到的点的最小次数,线性推 次就好,同样记录

因为 走的顺序不重要,所以枚举 , 代表从 走到 ,再从 走到终点,然后取最小的一个走法。

最终代码:

#include<bits/stdc++.h>
#define ll long long
#define MX 1000000000000ll
#define MXN 1000002
using namespace std;
inline void rd(ll &x){x=0;short f=1;char c=getchar();while((c<'0'||c>'9')&&c!='-') c=getchar();if(c=='-') f=-1,c=getchar();while(c>='0'&&c<='9') x=x*10+c-'0',c=getchar();x*=f;}
inline void pt(ll x){if(x<0) putchar('-'),x=-x;if(x>9) pt(x/10);putchar(x%10+'0');}

ll T=1,n,k,a,b,x,y,fx[MXN],fy[MXN],ans;//fx是x的走法,fy是y的走法
void solve(){
    rd(n),rd(k),rd(a),rd(b),rd(x),rd(y);
    ans=MX;
    for(ll i=0;i<n;i++)
        fx[i]=fy[i]=MX;
    for(ll i=0;i<n;i++){
        if(fx[i*x%n]==MX) fx[i*x%n]=i;//如果没走到过,就记录最小次数
        if(fy[i*y%n]==MX) fy[i*y%n]=i;
    }
    for(ll i=0;i<n;i++){
        ans=min(ans,fy[i]+fx[(i+b-a+n)%n]);//fx顺时针走i+b-a,fy逆时针走i,故走了b-a(注释为了方便没取模)
        if(k) ans=min(ans,fy[i]+fx[(i+b-a+n+n/2)%n]+1);//fx顺时针走i+b-a+n/2,fy逆时针走i,还走了一个n/2,故走了b-a
    }
    pt(ans==MX?-1:ans),puts("");//如果ans没被更新过,说明走不到
}int main(){while(T--) solve();}