1213解的个数——codevs

来源:互联网 发布:癫佬正传观后感知乎 编辑:程序博客网 时间:2024/05/17 06:45

” 数论只会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/gb[ 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 longusing 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();}}


0 0
原创粉丝点击