给定方程 \(Ax+By+C=0\)
要求 \(x_1 \le x \le x_2\) , \(y_1 \le y \le y_2\)
求整数解的个数
若 \(A,B,C\) 中有 \(0\),就变成了一元一次,这个直接模拟就好
\(exgcd\)
用来求解
\[ ax+by=c \]
这类方程,且仅当 \(\gcd(a,b)|c\) 时方程有整数解
若 \(k=\gcd(a,b,c)\) 且 \(k>1\),那就把 \(a,b,c\) 都除以 \(k\) ,让 \(c=\gcd(a,b)\)
\[ ax+by=\gcd(a,b) \]
设 \(a_1=b,b_1=a\%b\),即 \(b_1=a-\lfloor \frac ab \rfloor \times b\)
有 \(\gcd(a,b)=\gcd(a_1,b_1)\)
所以(这里用 \(x_1,y_1\) 代表另一组解)
\[ a_1 \times x_1+b_1 \times y_1=\gcd(a_1,b_1)=\gcd(a,b) \]
\[ b \times x_1+(a-\lfloor \frac ab \rfloor*b) \times y_1=\gcd(a,b) \]
\[ b \times x_1+a \times y_1-\lfloor \frac ab \rfloor \times b \times y_1=\gcd(a,b) \]
\[ b \times x_1-b \times \lfloor \frac ab \rfloor \times y_1+a \times y_1=\gcd(a,b) \]
\[ b \times (x_1-\lfloor \frac ab \rfloor \times y_1)+a \times y_1=\gcd(a,b) \]
\[ a \times y_1+b \times (x_1-\lfloor \frac ab \rfloor \times y_1)=\gcd(a,b) \]
于是得出了
\[ \left\{ \begin{aligned} a \times y_1 & +b \times (x_1-\lfloor \frac ab \rfloor \times y_1)&=\gcd(a,b)\\ a \times x & +b \times y&=\gcd(a,b) \end{aligned} \right. \]
对比一下就发现了
\[ \left\{ \begin{aligned} x&=y_1\\ y&=x_1-\lfloor \frac ab \rfloor \times y_1 \end{aligned} \right. \]
这就可以像 \(\gcd\) 一样递归做了
当递归到 \(b=0\) 的时候,就有特解了
\[ ax+by=\gcd(a,b) \]
我们知道 \(\gcd\) 递归到 \(b=0\) 的时候返回的是 \(a\)
于是把 \(\gcd(a,b)\) 换成 \(a\)
\[ ax+by=a \]
因为 \(b=0\)
\[ ax=a \]
于是得出特解 \(x=1,y=0\) ,其实 \(y\) 可以随便选但是要防止答案爆掉
然后就是模拟了
时间复杂度 \(O(T\log1e8)\)
// This code writed by chtholly_micromaker(MicroMaker)
#include <bits/stdc++.h>
#define reg register
#define int long long
using namespace std;
template <class t> inline void read(t &s)
{
s=0;
reg int f=1;
reg char c=getchar();
while(!isdigit(c))
{
if(c=='-')
f=-1;
c=getchar();
}
while(isdigit(c))
s=(s<<3)+(s<<1)+(c^48),c=getchar();
s*=f;
return;
}
inline int exgcd(int a,int b,int &x,int &y)
{
if(!b)
{
x=1,y=0;
return a;
}
reg int c=exgcd(b,a%b,y,x);
y-=a/b*x;
return c;
}
inline void work()
{
reg int A,B,C,xs,xt,ys,yt;
read(A);read(B);read(C);read(xs);read(xt);read(ys);read(yt);
if(!A&&!B)
{
if(!C)
printf("%lld\n",(yt-ys+1)*(xt-xs+1));
else
puts("0");
return;
}
if(!A)
{
if(C%B)
{
puts("0");
return;
}
if(ys<=-C/B&&-C/B<=yt)
printf("%lld\n",xt-xs+1);
else
puts("0");
return;
}
if(!B)
{
if(C%A)
{
puts("0");
return;
}
if(xs<=-C/A&&-C/A<=xt)
printf("%lld\n",yt-ys+1);
else
puts("0");
return;
}
C*=-1ll;
if(A<0)
{
A*=-1ll;
swap(xs,xt);
xs*=-1ll;
xt*=-1ll;
}
if(B<0)
{
B*=-1ll;
swap(ys,yt);
ys*=-1ll;
yt*=-1ll;
}
reg int x0,y0;
reg int g=__gcd(A,B);
if(C%g)
{
puts("0");
return;
}
exgcd(A,B,x0,y0);
A/=g;B/=g;
x0=C/g*x0;y0=C/g*y0;
reg double xL=(double)(xs-x0)/B;
reg double xR=(double)(xt-x0)/B;
reg double yL=(double)(y0-yt)/A;
reg double yR=(double)(y0-ys)/A;
// if(xL>xR)
// swap(xL,xR);
// if(yL>yR)
// swap(yL,yR);
reg int solL=max(ceil(xL),ceil(yL));
reg int solR=min(floor(xR),floor(yR));
// printf("x0 %lld y0 %lld\n",x0,y0);
// printf("xt %lld %lld\n",(int)ceil(xL),(int)floor(xR));
// printf("yt %lld %lld\n",(int)ceil(yL),(int)floor(yR));
printf("%lld\n",max(0ll,solR-solL+1));
return;
}
signed main(void)
{
int T;cin>>T;
for(int i=1;i<=T;++i)
printf("Case %lld: ",i),work();
return 0;
}