这一篇文章的主角就是大名鼎鼎的数学家欧几里得。很多刚了解一些数论的ACMer都会接触到辗转相除法,其实这就叫做欧几里得算法,但是这并不会是我们今天所讲的内容,我们今天讲的算法叫做扩展欧几里得。
扩展欧几里得 这个算法主要就是求一个式子的解:ax+by=gcd(a,b) 首先我们可以知道当b=0时,即有x=1,y=0,当b>0的时候我们可以进行推导,因为gcd(a,b)=gcd(b,a mod b),我们可以带入式子推出bx‘+(a mod b)y’=gcd(b,a mod b)=gcd(a,b),我们可以回代得到下面的式子 bx’+(a-a/b*b)y’=gcd(a,b) ay’+bx’-(a/b)*by’=gcd(a,b) ay’+b(x’-a/b*y’)=gcd(a,b) 最后我们可以和最初的式子ax+by=gcd(a,b)一起得出x=y’,y=x’-a/b*y’ 这样我们就可以求出这个式子的解了
直线上的点 求直线上ax+by+c=0有多少个整数点(x,y),使得其满足x属于[x1,x2],y属于[y1,y2]。
我们可以先利用扩展欧几里得求出一组解,然后通过这一组解就可以得到所有的解了
代码 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 #include <iostream> using namespace std;int extend_gcd (int a,int b,int &x,int &y) { if (b==0 ){ x=1 ; y=0 ; return a; }else { int r=extend_gcd (b,a%b,y,x); y-=x*(a/b); return r; } } int main () { cout << "请依次输入a,b,c,x1,x2,y1,y2:" ; int a,b,c,x,y,x1,x2,y1,y2; cin>>a>>b>>c>>x1>>x2>>y1>>y2; int g=extend_gcd (a,b,x,y); if (c%g==0 ){ int x0 = -x*(c / g), y0 = -y*(c / g); cout << '(' << x0 << ',' << y0 << ')' << endl; bool kup = true , kdown = true ; for (int k = 1 ;; k++){ int xn = x0 - k*(b/g), yn = y0 + k*(a/g); if (kup&&xn >= x1&&xn <= x2&&yn >= y1&&yn <= y2) cout << '(' << xn << ',' << yn << ')' << endl; else kup = false ; xn = x0 + k*(b / g); yn = y0 - k*(a / g); if (kdown&&xn >= x1&&xn <= x2&&yn >= y1&&yn <= y2) cout << '(' << xn << ',' << yn << ')' << endl; else kdown = false ; if (!(kup || kdown)) break ; } }else cout << "No Point." << endl; return 0 ; }