” 数论只会gcd“ 系列
ax+by+c=0
变形ax+by=-c
用拓展欧几里得定理做
找出一组最小符合要求解之后
再来拓展出其他在pq rs 范围内的数
变形 a(x+b)+b(y-a)=-c
这样可以拓展出一些其他的解 但是这样并不是最多
会漏掉一些解
因为有一个比a,b更小的常数可以用来加减
设a(x+u)+b(y-v)=-c
ax+by+au-bv=-c
因为ax+by=-c
得到
au-bv=0
au=bv
u=v*b/a
要使u是最小正整数
即是v*b/a最小整数
去掉分母就是目的了
当然去掉的a是越小越好了 这样b也越小 b*v的整数就越小
就设g=gcd(a,b)
u=v*(b/g)/(a/g)
得到互质的a/g b/g
再变换回来(刚才过程是为了推导。)
u*(a/g)=v*(b/g)
要使两边的数 乘上一个互质的数 相等
就是要让 左边的因子 和右边的因子 一样多 一样大
而(a/g)与(b/g)互质
就只有从uv上找因子互补了
对于(a/g) 缺少的是 (b/g) u=b/g
对于(b/g) 缺少的是 (a/g) v=a/g
于是 a[ x+(b/g) ] + b[ y-(a/g) ] = -c
或者 a[ x-(b/g) ] + b[ y+(a/g) ] = -c (两个方向 变大变小拓展)
结束条件 就保存上一次的x或者y
如果当前的值减去区间中位数的abs相比上一次变大了 却又不在区间之内
就break
于是就ok了
吐槽codevs 数据居然有系数0。。
还有p>q 说好的[p,q]区间呢 。。
好吧 可能是我自己思维不够 orzorz
#include<cstdio>
#define abs(a) ((a<0)?(-a):(a))
#define LL long long
using namespace std;
LL n,now,ans;
LL bx,by;
LL a,b,c,p,q,r,s;
LL x,y;
LL temp;
void readdata(){
scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&p,&q,&r,&s);
}
LL gcd(LL a,LL b){
if(b)
return gcd(b,a%b);
else return a;
}
void ex_gcd(LL aa,LL bb,LL &x,LL &y){
if(bb){
ex_gcd(bb,aa%bb,x,y);
temp=x;
x=y;
y=temp-aa/bb*y;
}
else x=-c/now,y=0;
}
void solve(){
ans=0;
if(p>q||r>s){
return;
}
if(a==0&&b==0){
if(c==0){
LL hehe=q-p;
LL hehehe=s-r;
ans=(abs(hehe)+1)*(abs(hehehe)+1);
}
return;
}
else{
if(a==0){
if((-c/b)>=r&&(-c/b)<=s)
if(-c/b*b==-c)
ans=q-p+1;
return;
}
else{
if(b==0){
if((-c/a)>=p&&(-c/a)<=q)
if(-c/a*a==-c)
ans=s-r+1;
return;
}
}
}
now=gcd(a,b);
if(-c%now){
return;
}
ex_gcd(a,b,x,y);
LL midpq=(q+p)/2;
LL midrs=(r+s)/2;
bx=x;
by=y;
if(bx>=p&&bx<=q&&by>=r&&by<=s){
ans++;
}
LL jx=x;
LL jy=y;
LL tx2,tx1;
LL ty2,ty1;
while(1){
bx+=b/now;
by-=a/now;
if(bx>=p&&bx<=q&&by>=r&&by<=s){
ans++;
}
else{
tx1=jx-midpq;tx2=bx-midpq;
ty1=jy-midrs;ty2=by-midrs;
if(abs(tx1)<abs(tx2)&&abs(ty1)<abs(ty2)){
break;
}
jx=bx;
jy=by;
}
}
jx=x;
jy=y;
while(1){
x-=b/now;
y+=a/now;
if(x>=p&&x<=q&&y>=r&&y<=s){
ans++;
}
else{
tx1=jx-midpq;tx2=x-midpq;
ty1=jy-midrs;ty2=y-midrs;
if(abs(tx1)<abs(tx2)&&abs(ty1)<abs(ty2)){
break;
}
jx=x;
jy=y;
}
}
}
void print(){
printf("%lld\n",ans);
}
int main(){
scanf("%lld",&n);
while(n--){
readdata();
solve();
print();
}
}
本文探讨了数论中的基本概念,特别是通过扩展欧几里得定理来解决形如ax+by+c=0的线性方程组。文中详细解释了如何通过该定理找到一组最小符合要求的解,并在此基础上拓展出一系列解,同时考虑了解的范围限制。此外,文章还提出了在特定区间内求解的方法,并通过实例代码演示了实现过程。
1327

被折叠的 条评论
为什么被折叠?



