解法:
先确定5个参数之间关系,建设存在时间t和圈数k满足:
s1+v1*t=s2+v2*t-k*m (v1<v2)
(v1-v2)*t+k*m=(s2-s1)
—————— —— ——————
A B C
看成Ax+By=C,求通解(x,y)使等式成立。使用扩展欧几里得算法。
上式成立的条件是,方程有解,既c为A,B最大公约数的整数倍。
欧几里得算法:是用来求解最大公约数的一种算法,大概思路是gcd(a, b) = gcd(b , a%b),辗转相除法,这样做的好处是算法时间复杂度比枚举大大降低。logn级别。
a%b=0则,a、b的最大公约数为b。
a%b!=0,则gcd(a, b) = gcd(b , a%b)。
通过递归,降低数据的规模,得到一个解。
而扩展欧几里得算法,在欧几里得算法的基础上,再求一组(x,y),ABC均为gcd(A,B)的整数倍,ABC同时缩小gcd(A,B)。
得到A'x+B'y=C',gcd(A',B')=1,A',B'互质(A,B的最大公约数为1)
取2组解
A * x1 + B * y1 = gcd(A, B)
B * x2 + (A % B) * y2 = gcd(B, A % B)
化简为
x1 = y2, y1 = (x2 - ky2)
递归求解(x,y)
终止条件为x=0,y=1;
1 #include <iostream>
2 typedef long long LL;
3 using namespace std;
4
5 LL gcd(LL a,LL b){
6 if(b==0)
7 return a;
8 return gcd(b,a%b);
9 }
10
11 LL extend_gcd(LL a, LL b,LL &x,LL &y){
12 if(a%b!=0){
13 x=1;
14 y=0;
15 return a;
16 }
17
18 LL ans=extend_gcd(b,a%b,x,y);
19 LL temp=x;
20 x=y;
21 y=temp-(a/b)*y;
22 return ans;
23
24 }
25
26 int main(){
27 LL s1,s2,v1,v2,m;
28 cin>>s1>>s2>>v1>>v2>>m;
29
30 LL A,B,C,D,x,y;
31
32 A = v1 - v2;
33 B = m;
34 C = s2 - s1;
35
36 if (A < 0)
37 A = A + m ;
38 D = gcd(A, B);
39
40 if (C % D)
41 cout<<-1<<endl;
42
43 A = A / D;
44 B = B / D;
45 C = C / D;
46
47 x = extend_gcd(A, B,x,y);
48 x = (x * C) % B;
49 while (x < 0){
50 x = x + B;
51 }
52 cout<<x<<endl;
53
54 }
自己的机器上跑没问题,提交hiho总是WA,伤不起。有大神可以指点一二就好了。