Codeforces Round #305 (Div. 2)——C拓展欧几里得,循环—— Mike and Frog
2015-05-27 16:16
525 查看
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.
Input
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.
Output
Print the minimum number of seconds until Xaniar reaches height a1 and Abol reaches height a2 or print -1 otherwise.
Sample test(s)
input
output
input
output
Note
In the first sample, heights sequences are following:
Xaniar:
Abol:
大意:x = (kx+b)%m 在2*m次里面能看出是否能够到达所有的值
法一:暴力
法二:拓展欧几里得
用于处理计算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
可以得到其中一个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
以上都是些结论
详细证明 请看 /article/6002647.html 大神写的非常好orz
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.
Input
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.
Output
Print the minimum number of seconds until Xaniar reaches height a1 and Abol reaches height a2 or print -1 otherwise.
Sample test(s)
input
5 4 2 1 1 0 1 2 3
output
3
input
1023 1 2 1 0 1 2 1 1
output
-1
Note
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\n",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
以上都是些结论
详细证明 请看 /article/6002647.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\n",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\n",ans); } return 0; }
相关文章推荐
- Codeforces 547 Div1 A. Mike and Frog(找循环节)
- Codeforces Round #305 (Div. 2) C. Mike and Frog +B. Mike and Fun
- CF #305 (Div. 2) C. Mike and Frog(扩展欧几里得&&当然暴力is also no problem)
- Codeforces Round #305 (Div. 2)C---Mike and Frog(扩欧+乱搞)
- Codeforces Round #305 (Div. 2) C. Mike and Frog
- Codeforces Round #305 (Div. 2) C. Mike and Frog
- Codeforces Round #305 (Div. 2)C. Mike and Frog 数学(循环节)
- Codeforces Round #305 (Div. 2) 548C - Mike and Frog 循环节
- 数论/暴力 Codeforces Round #305 (Div. 2) C. Mike and Frog
- Codeforces Round #305 (Div. 1) A. Mike and Frog(数学)
- Codeforces Round #305 (Div. 1) A. Mike and Frog 暴力
- Codeforces Round #410 (Div. 2)-A. Mike and palindrome-思维
- Codeforces Round #305 (Div. 2) A. Mike and Fax 暴力回文串
- Mike and Frog - CodeForces #547 A
- 字符串k在第li到第ri个字符串中一共出现了几次 后缀数组+线段树 Codeforces Div. 1E. Mike and Friends
- Codeforces Round #285 (Div. 2) D. Misha and Permutations Summation 康拓展开 平衡树优化
- Codeforces Round #410 (Div. 2) D. Mike and distribution(贪心)
- Mike and gcd problem Codeforces Round #410 (Div. 2)
- Codeforces Round #305 (Div. 2) D. Mike and Feet (单调栈)
- Codeforces Round #305 (Div. 2) B. Mike and Fun 暴力