求直线 a x + b y + c = 0 ax+by+c=0 ax+by+c=0上有多少个整点 ( x , y ) (x,y) (x,y)满足 x ∈ [ x 1 , x 2 ] , y ∈ [ y 1 , y 2 ] x\in[x1,x2],y\in[y1,y2] x∈[x1,x2],y∈[y1,y2]
在解决引中的问题之前,我们需要学习一下扩展欧几里得算法——找出一对整数对 ( x , y ) (x,y) (x,y)使其满足 a x + b y = g c d ( a , b ) ax+by=gcd(a,b) ax+by=gcd(a,b)
例: a = 6 , b = 15 , g c d ( a , b ) = 3 , 6 ∗ 3 − 15 ∗ 1 = 3 a=6,b=15,gcd(a,b)=3,6*3-15*1=3 a=6,b=15,gcd(a,b)=3,6∗3−15∗1=3,其中 x = 3 , y = − 1 x=3,y=-1 x=3,y=−1且有其他解存在
下面是刘汝佳sama的代码
void exgcd(int a,int b,int &d,int &x,int &y){
if(!b) d=a,x=1,y=0;
else gcd(b,a%b,d,y,x),y-=x*(a/b);
}
首先,扩展欧几里得算法是通过递归求解的,那么怎么进入下一层递归呢?
设 a x + b y = d , a = t b + r ( a > = b ) ax+by=d,a=tb+r(a>=b) ax+by=d,a=tb+r(a>=b)
其中 t = ⌊ a b ⌋ , r = a % b t={\lfloor {a\over b}\rfloor},r=a\%b t=⌊ba⌋,r=a%b
代入得 t b x + r x + b y = d tbx+rx+by=d tbx+rx+by=d
整理得 b ( t x + y ) + r x = d b(tx+y)+rx=d b(tx+y)+rx=d
惊奇的发现,式子化成了 a x + b y = d ax+by=d ax+by=d的形式
那么此时我们设当前层的 x , y x,y x,y为 x n o w , y n o w x_{now},y_{now} xnow,ynow
下一层的 x , y x,y x,y为 x n e x t , y n e x t x_{next},y_{next} xnext,ynext
由此可得 x n e x t = t x n o w + y n o w , y n e x t = x n o w x_{next}=tx_{now}+y_{now},y_{next}=x_{now} xnext=txnow+ynow,ynext=xnow
同时,下一层的 a , b a,b a,b也确定了
a n e x t = b n o w , b n e x t = a n o w % b n o w a_{next}=b_{now},b_{next}=a_{now}\%b_{now} anext=bnow,bnext=anow%bnow
由下至上求解,所以当前层在取用上一层递归的时候需要一点操作
先求当前层的x,根据上面推出的公式不难得出 x n o w = y n e x t x_{now}=y_{next} xnow=ynext
在求y时,我们先让y等于上一层的x,再减去上一层的 x ∗ ⌊ a b ⌋ x*{\lfloor{a\over b}\rfloor} x∗⌊ba⌋就是y啦( y n o w = x n e x t − t x n o w y_{now}=x_{next}-tx_{now} ynow=xnext−txnow)
因为是递归求解,那么终止条件是什么呢?
不难看出,当 b = 0 b=0 b=0时, g c d ( a , 0 ) = a ∗ 1 − 0 ∗ 0 = a gcd(a,0)=a*1-0*0=a gcd(a,0)=a∗1−0∗0=a,此时 x = 1 , y = 0 x=1,y=0 x=1,y=0
刘汝佳的代码真是太好理解啦,所以我写一个难理解的
pair<int,int> exgcd(int a,int b,int &d){//返回的是x,y
if(!b) { d=a;return make_pair(1,0); }
auto [y,x]=exgcd(b,a%b,d);
return make_pair(x,y-x*(a/b));//注意这里不用反过来
}
上面求出了一组解 ( x 1 , y 1 ) (x_1,y_1) (x1,y1),那么其他解呢?
另取任意一组解 ( x 2 , y 2 ) (x_2,y_2) (x2,y2)
则有 a x 1 + b y 1 = a x 2 + b y 2 ax_1+by_1=ax_2+by_2 ax1+by1=ax2+by2,变形得 a ( x 1 − x 2 ) = b ( y 2 − y 1 ) a(x_1-x_2)=b(y_2-y_1) a(x1−x2)=b(y2−y1)
设 g c d ( a , b ) = g gcd(a,b)=g gcd(a,b)=g,那么让两遍都除以g,得 a ′ ( x 1 − x 2 ) = b ′ ( y 2 − y 1 ) ( a ′ 与 b ′ 互质 ) a'(x_1-x_2)=b'(y_2-y_1)(a'与b'互质) a′(x1−x2)=b′(y2−y1)(a′与b′互质)
因此 ( x 1 − x 2 ) (x_1-x_2) (x1−x2)一定是 b ′ b' b′的整数倍,为什么呢?
a ′ ( x 1 − x 2 ) b ′ = y 2 − y 1 {a'(x_1-x_2)\over b'}=y_2-y_1 b′a′(x1−x2)=y2−y1因为 a ′ , b ′ a',b' a′,b′互质,所以 x 1 − x 2 x_1-x_2 x1−x2可以将 b ′ b' b′约去来得到整数 y 2 − y 1 y_2-y_1 y2−y1
设 x 1 − x 2 = k b ′ x_1-x_2=kb' x1−x2=kb′,得 y 2 − y 1 = k a ′ y_2-y_1=ka' y2−y1=ka′
所以,若方程 a x + b y = c ax+by=c ax+by=c的一组解为 ( x 0 , y 0 ) (x_0,y_0) (x0,y0)
那么其他任意解均可写成 ( x 0 + k b ′ , y 0 − k b ′ ) (x_0+kb',y_0-kb') (x0+kb′,y0−kb′)
有了这个结论,移项得 a x + b y = − c ax+by=-c ax+by=−c然后求出一组解即可
由此可得: g = g c d ( a , b ) , a x + b y = g g=gcd(a,b),ax+by=g g=gcd(a,b),ax+by=g的一组解为 ( x 0 , y 0 ) (x_0,y_0) (x0,y0),当c为g的整数倍数时存在解 ( x 0 c / g , y 0 c / g ) (x_0c/g,y_0c/g) (x0c/g,y0c/g),否则无解
至此才算是完整解决了引中的问题
所以,感谢刘的讲解
完结撒花