a,b是整数,m是正整数,形如a * x ≡ b (mod m),且x是未知数的同余式称为一元线性同余方程。
定理1:假设d = gcd(a , m),假设对于整数xx和yy有 d = a * xx + m * yy。若d|b(d能够整出b),那么方程 a * x ≡ b (mod m)有一个解X满足式子 X = xx * (a/b) % m ,其中xx可以用扩展欧几里得算法获得。
扩展欧几里得算法详解见:http://www.cnblogs.com/heweiyou1993/p/3301873.html
1 long long ExtendedEuclid(long long a,long long b,long long& d,long long& x,long long& y) 2 { 3 long long tmp; 4 if(b == 0) 5 { 6 x = 1; 7 y = 0; 8 d = a; 9 }else 10 { 11 ExtendedEuclid(b,a%b,d,x,y); 12 tmp = x; 13 x = y; 14 y = tmp - (a / b) * y; 15 } 16 }
扩展欧几里得源码:
证明1:假设上述成立那么有 a * X ≡ a * xx * (b/d)(mod m),由于a * xx ≡ d (mod m),所以可得到 a * X ≡ d * (b/d)(mod m) ≡ b(mod m)。
定理2:对于a * x ≡ b (mod m),若有解则必有d = gcd( a, m)个解。其解为 res = (X + i * ( b / d)) (mod m),其中X为远同余方程的一个解,i的取值范围为 0 <= i < d。
证明2:若定理2成立则有 a * res (mod m) = a * (X + i * (b / d)) (mod m) = a * X + a* i * (b /d) (mod m) = a * X (mod m) = b。
源代码如下:
1 void RemainderEquation(long long a,long long b,long long m) 2 { 3 long long X,Y,d; 4 long long res; 5 ExtendedEuclid(a,m,d,X,Y); 6 7 if(b%d == 0) 8 { 9 X = X * (b / d) % m;//得到同于方程一解 10 for(int i = 0 ; i < d; i++) 11 { 12 res = (X + (i * (b/d))) % m; 13 printf("%lld\n",res); 14 } 15 }else 16 { 17 printf("No Sulutions!\n"); 18 } 19 }
由于一元线性同余方程的通解可以写成res = ( X + i * (b /d) ) (mod m) = X + i * (m/d) + m * y,由于 y 与 i 均为变量因此可以将其合并得到式子 res = X + y * ( m/d) (其中将原式中的 m * y 看做 m/d * d * y,由于y是变量因此可以将 d*y这个整体看为 y),因此可以得到res = X(mod m/d) ,设m/d 为 t ,其最小正整数解可表示为 (X%t + t) % t。