Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 17238 | Accepted: 4462 |
Description
for (variable = A; variable != B; variable += C) statement;
Input
Output
Sample Input
3 3 2 16 3 7 2 16 7 3 2 16 3 4 2 16 0 0 0 0
Sample Output
0 2 32766 FOREVER
Source
参考:
根据题意可以推导出公式:
A + C * X ≡ B (MOD 2^k ) (X=0,1,2,.......)
及: C * X + 2^k * Y = B-A (X=0,1,2,........ Y=0,1,2,3......)
http://blog.csdn.net/lyy289065406/article/details/6648546http://www.cnblogs.com/frog112111/archive/2012/08/19/2646012.html //这篇文章讲得很好。
http://www.cnblogs.com/ACSeed/archive/2013/01/31/2887248.html
1)求解线性不定方程
ax + by = c
先求出一组解, 然后考虑如何表示通解, 设d = gcd(a, b), 假设c不是d的倍数, 则左边是d的倍数而右边不是, 则方程无解, 所以方程有解当且仅当d | c.
设c = c' * d, 我们先考虑方程 ax + by = d, 这样由扩展gcd便可求出一组解 (x', y'), 则(c'x', c'y')就是原方程的一组解,然后考虑通解:
假设有两组解(x1, y2) , (x2, y2), 有 ax1 + by1 == ax2 + by2 = c, 移项得: a(x1 - x2) == b(y2 - y1), 消去d后有 a'(x1 - x2) == b'(y2 - y1),
此时a' 和 b' 互素, 所以(x1 - x2)一定是b'的倍数, 而(y2 - y1)一定是a'的倍数, 由此可得到通解:
给一组特解(x, y), 通解为(x - kb', y + ka').
2)求解模线性方程
ax = b(mod n)
其实方程等价于 ax - ny = b, 标准模线性方程,但是得考虑剩余系。
算法导论上有两个定理:
定理一:设d = gcd(a, n), 假定对整数x', y', 有d = ax' + ny', 如果d | b, 则方程ax = b(mod)有一个解的值为x0, 满足:、
x0 = x'(b / d)(mod n)
定理二:假设方程ax = b(mod n)有解, x0是方程的任意一个解, 则方程对模n恰有d个不同的解, 分别为: xi = x0 + i * (n / d), 其中 i = 1,2,3......d - 1
有了这两个定理, 解方程就不难了。
1 void linear_mod_equation (int a, int b, int n, int *sol) 2 { 3 int d, x, y; 4 gcd (a, n, d, x, y ); 5 if (b % d) d = 0; 6 else 7 { 8 sol [0] = x * ( b / d ) % n ; 9 for (int i = 1; i < d; ++i) 10 sol[i] = (sol[i - 1] + n / d) % n ; 11 } 12 }
如果gcd(a, n) == 1, 则方程有唯一解, 即解为a的逆。
1 ll inv(ll a, ll n) 2 { 3 ll d, x, y; 4 gcd(a, n, d, x, y); 5 return d == 1 ? (x % n + n) % n : -1; 6 }
long long exgcd(long long a,long long b,long long &x,long long &y)//扩展欧几里得算法,返回a,b的最大公约数,ax+by=gcd(a,b),x,y为方程的一组解 { if(b==0) { x=1; y=0; return a; } long long d=exgcd(b,a%b,x,y); long long t=x; x=y; y=t-a/b*y; return d; }
long long modular_liner_equation(long long a,long long b,long long n)//求解模线性方程ax=b(mod n) { long long x,y,x0; long long d=exgcd(a,n,x,y); if(b%d)//没有解 return -1; x0=(x*(b/d))%n;//特解 //for(int i=1;i<d;i++) //cout<<(x0+i*(n/d))%n; long long ans=x0,s=n/d; ans=(ans%s+s)%s; //ans为最小整数解 return ans; }
#include <iostream> #include <string.h> using namespace std; long long exgcd(long long a,long long b,long long &x,long long &y)//扩展欧几里得算法,返回a,b的最大公约数,ax+by=gcd(a,b),x,y为方程的一组解 { if(b==0) { x=1; y=0; return a; } long long d=exgcd(b,a%b,x,y); long long t=x; x=y; y=t-a/b*y; return d; } long long modular_liner_equation(long long a,long long b,long long n)//求解模线性方程ax=b(mod n) { long long x,y,x0; long long d=exgcd(a,n,x,y); if(b%d)//没有解 return -1; x0=(x*(b/d))%n;//特解 //for(int i=1;i<d;i++) //cout<<(x0+i*(n/d))%n; long long ans=x0,s=n/d; ans=(ans%s+s)%s; //ans为最小整数解 return ans; } int main() { long long A,B,C,k; while(cin>>A>>B>>C>>k&&(A||B||C||k)) { long long a=C; long long b=B-A; long long n=1LL<<k; long long ans=modular_liner_equation(a,b,n); if(ans==-1) cout<<"FOREVER"<<endl; else cout<<ans<<endl; } return 0; }