D题的妙妙解法:
时间复杂度
思路:
我这里的点是从 到
。
因为 走两次及以上没有意义(走回来了),将
分两种:
-
若
答案为从
走到
(等价于从
到
)。
-
若
答案取
上面的值
与
从
走到
(等价于从
到
)加上一
最小的那个。
我们记录用 能走到的点的最小次数,线性推
次就好,同样记录
。
因为 、
走的顺序不重要,所以枚举
, 代表从
按
走到
,再从
按
走到终点,然后取最小的一个走法。
最终代码:
#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();}