1. 程式人生 > >LightOJ - 1306 Solutions to an Equation

LightOJ - 1306 Solutions to an Equation

範圍 a* 代碼 -1 最大公約數 scanf bsp std color

技術分享

題目大意:給你一個方程ax+by+c=0(x1<=x<=x2&&y1<=y<=y2)

求其整數解個數

具體思路:擴展歐幾裏得求一個特解,然後求一下x和y的最少變化量,

然後求出當x1<=x<=x2,與其對應的y的範圍,和y1<=y<=y2做一個並,在算一下有幾個解就好了

花絮:一開始我發現x=x0+xx*t(x0為特解,xx為最少變化量)y=y0-yy*t,並試圖求出t的範圍,wa了幾發之後發現有許多+1-1的奇怪地方需要處理,於是果斷換了一個做法

結果卻還是wa,通過一些特殊手段發現好像是我為了把方程變為ax+by=c,我把讀入的c取反,但前面的特判寫的比較早~~~

擴展歐幾裏得是什麽勒?

歐幾裏得算法可以求最大公約數

int gcd(int a,int b){if(b==0)return a;else return gcd(b,a%b);}

然後擴展歐幾裏得可以求ax+by=gcd(a,b)的一組解

怎麽求的呢?

因為gcd(a,b)=gcd(b,a%b)

所以ax+by=gcd(a,b)可以變為

b*x1+(a%b)*y1=gcd(b,a%b)=ax+by

然後一頓公式變形

b*x1+(a%b)*y1=b*x1+(a-[a/b]*b)*y1([]為下取整)

=b*x1+(a-[a/b]*b)*y1=a*y1+b*(x1-[a/b]*y1)=ax+by

所以x=y1 y=x1-[a/b]*y1

於是可以寫成這樣

void exgcd(int a,int b,int& d,int& x,int & y)
{
    if(b==0)d=a,x=1,y=0;
    else exgcd(b,a%b,d,y,x),y-=(a/b)*x;
}

最後是AC代碼

#include<cstdio>
#include<algorithm>
#include<cmath>
#define int long long 
using namespace std;
int T;
int gcd(int
a,int b){if(b==0)return a;else return gcd(b,a%b);} void exgcd(int a,int b,int& d,int& x,int & y) { if(b==0)d=a,x=1,y=0; else exgcd(b,a%b,d,y,x),y-=(a/b)*x; } main() { scanf("%lld",&T); int t; for (t=1;t<=T;t++) { int a,b,c,X1,X2,Y1,Y2; scanf("%lld%lld%lld%lld%lld%lld%lld",&a,&b,&c,&X1,&X2,&Y1,&Y2);c=-c; printf("Case %lld: ",t); if(a==0&&b==0) { if(c==0) printf("%lld\n",(Y2-Y1+1)*(X2-X1+1));else puts("0"); continue; } else if(a==0) { if(c%b!=0) puts("0"); else { int z=c/b; if(z>=Y1&&z<=Y2) printf("%lld\n",(X2-X1+1));else puts("0"); } continue; } else if(b==0) { int z=c/a; if(c%a!=0) puts("0"); else if(z>=X1&&z<=X2) printf("%lld\n",(Y2-Y1+1)); else puts("0"); continue; } int g=gcd(a,b); if(c%g) { puts("0"); continue; } int x,y; exgcd(a,b,g,x,y); x=x*(c/g),y=y*(c/g); int xx=b/g,yy=a/g,Ymn,Ymx; X1=((x-X1)%xx+abs(xx))%abs(xx)+X1; X2=((x-X2)%xx-abs(xx))%abs(xx)+X2; if(X1>X2){printf("0\n");continue;} Ymn=(-yy)*((X1-x)/xx)+y; Ymx=(-yy)*((X2-x)/xx)+y; if(Ymn>Ymx)swap(Ymn,Ymx); Y1=max(Y1,Ymn); Y2=min(Y2,Ymx); Y1=((y-Y1)%yy+abs(yy))%abs(yy)+Y1; Y2=((y-Y2)%yy-abs(yy))%abs(yy)+Y2; if(Y1>Y2)puts("0");else printf("%lld\n",(Y2-Y1)/abs(yy)+1); } return 0; }

LightOJ - 1306 Solutions to an Equation