Mike has a frog and a flower. His frog is named Xaniar and his flower is named Abol. Initially(at time 0), height of Xaniar is h1 and height of Abol is h2. Each second, Mike waters Abol and Xaniar.

So, if height of Xaniar is h1 and height of Abol is h2, after one second height of Xaniar will become and height of Abol will become
where x1, y1, x2 and y2 are some integer numbers and
denotes the remainder of amodulo b.
Mike is a competitive programmer fan. He wants to know the minimum time it takes until height of Xania is a1 and height of Abol is a2.
Mike has asked you for your help. Calculate the minimum time or say it will never happen.
The first line of input contains integer m (2 ≤ m ≤ 106).
The second line of input contains integers h1 and a1 (0 ≤ h1, a1 < m).
The third line of input contains integers x1 and y1 (0 ≤ x1, y1 < m).
The fourth line of input contains integers h2 and a2 (0 ≤ h2, a2 < m).
The fifth line of input contains integers x2 and y2 (0 ≤ x2, y2 < m).
It is guaranteed that h1 ≠ a1 and h2 ≠ a2.
Print the minimum number of seconds until Xaniar reaches height a1 and Abol reaches height a2 or print -1 otherwise.
5
4 2
1 1
0 1
2 3
3
1023
1 2
1 0
1 2
1 1
-1
In the first sample, heights sequences are following:
Xaniar:
Abol:
大意:x = (kx+b)%m 在2*m次里面能看出是否能够到达所有的值
法一:暴力
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; int main() { long long m,h1,a1,x1,y1,h2,a2,x2,y2; long long p1,p2,q1,q2; while(cin >> m >> h1 >> a1 >> x1 >> y1 >> h2 >> a2 >> x2 >> y2){ p1 = p2 = q1 = q2 = 0; for(long long i = 1; i <= 2*m; i++){ h1 = (h1*x1+y1)%m; if(h1 == a1){ if(p1 == 0) p1 = i; else if(q1 == 0){ q1 = i - p1; break; } } } for(long long i = 1; i <= 2*m; i++){ h2 = (h2*x2+y2)%m; if(h2 == a2){ if(p2 == 0) p2 = i; else if(q2 == 0){ q2 = i - p2; break; } } } if(p1 == 0 || p2 == 0){ puts("-1"); continue; } long long ans1 = p1,ans2 = p2; long long i; for( i = 1; i <= 2 *m ;i++){ if(ans1 == ans2){ printf("%lld ",ans1); break; } if(ans1 > ans2){ ans2 += q2; } if(ans1 < ans2){ ans1 += q1; } } if( i > 2*m){ puts("-1"); } } return 0; }
法二:拓展欧几里得
用于处理计算ax+by = c 的x,y的值
由已知数据我们容易可以的出p1,q1,p2,q2,依次是h1到a1的开始的时间,循环的时间,h2到a2的开始的时间,循环的时间,那么可以得到p1x+q1 = p2x+q2
变形可得 p1x-p2x=q2-q1
欧几里得 ax+b = c gcd(a,b) = gcd(b,a%b) 当b=0时就是最大公约数,递归最大公约数的求法
int gcd(int a,int b){
return b == 0? a:gcd(b,a%b);
}
拓展欧几里得公式 ax+by=c
int exgcd(int a,int b){ if(b == 0){ x = 1; y = 0; return a; } int d = exgcd(b,a%b); int t = x; x = y; y = t - a/b*y; return d; }
可以得到其中一个x,y的解(对于ax+by = gcd(a,b) 这个方程)
定理:对于ax+by = gcd(a,b)来说肯定会存在x,y(为正整数)的解
所以最终的解为 x *= c/d,y *=c/d;如果c%d!=0说明无正整数解
那么对于所有的x,y解集满足条件
x = x + q2/d;
y = y - q1/d;
对于本题来说只要找到一个最小的x满足x,y都大于等于零,res = q1x+p1
以上都是些结论
详细证明 请看 http://www.cnblogs.com/ka200812/archive/2011/09/02/2164404.html 大神写的非常好orz
#include<cstdio> #include<cstring> #include<algorithm> #include<iostream> using namespace std; long long x,y; long long exgcd(long long a,long long b){ if(b == 0){ x = 1; y = 0; return a; } long long d = exgcd(b,a%b); long long t = x; x = y; y = t - a/b*y; return d; } int main() { long long m,h1,a1,x1,y1,h2,a2,x2,y2; long long p1,p2,q1,q2; while(cin >> m >> h1 >> a1 >> x1 >> y1 >> h2 >> a2 >> x2 >> y2){ p1 = p2 = q1 = q2 = 0; for(long long i = 1; i <= 2*m; i++){ h1 = (h1*x1+y1)%m; if(h1 == a1){ if(p1 == 0) p1 = i; else if(q1 == 0){ q1 = i - p1; break; } } } for(long long i = 1; i <= 2*m; i++){ h2 = (h2*x2+y2)%m; if(h2 == a2){ if(p2 == 0) p2 = i; else if(q2 == 0){ q2 = i - p2; break; } } } long long d = exgcd(q1,-q2); long long c = p2 - p1; if(d == 0){ puts("-1"); continue; } if(c%d){ puts("-1"); continue; } if(d < 0 ) d = -d; if(p1 == 0 || p2 == 0){ puts("-1"); continue; } if(q2 == 0 && q1 == 0 && p1 != p2){ puts("-1"); continue; } // printf("%I64d %I64d %I64d %I64d ",p1,p2,q1,q2); if((q2 == 0&&p2-p1 < 0) || (q1 == 0 && p1-p2< 0)){ puts("-1"); continue; } long long k = c/d; if(exgcd(q1,-q2) < 0) x = -x,y = -y; x*= k; y*= k; if(x < 0 || y < 0) for( ; ;){ x += q2/d; y += q1/d; if(x >= 0 && y >= 0) break; } if(x > 0 && y > 0){ for(; ;){ x -= q2/d; y -= q1/d; if( x < 0 || y < 0) break; } x += q2/d; y += q1/d; } long long ans = x*q1+p1; printf("%I64d ",ans); } return 0; }