[lightoj P1306] Solutions to an Equation
[lightoj P1306] Solutions to an Equation
You have to find the number of solutions of the following equation:
Ax + By + C = 0
Where A, B, C, x, y are integers and x1 ≤ x ≤ x2 and y1 ≤ y ≤ y2.
Input
Input starts with an integer T (≤ 10000), denoting the number of test cases.
Each case starts with a line containing seven integers A, B, C, x1
Output
For each case, print the case number and the total number of solutions.
Sample Input
5
1 1 -5 -5 10 2 4
-10 -8 80 -100 100 -90 90
2 3 -4 1 7 0 8
-2 -3 6 -2 5 -10 5
1 8 -32 0 0 1 10
Sample Output
Case 1: 3
Case 2: 37
Case 3: 1
Case 4: 2
Case 5: 1
毒瘤題。。。
首先肯定要用到exgcd。。都快忘了。
再推一下——
Ax0+By0=gcd(A,B)
= Bx+(A%B)y=gcd(B,A%B)
= Bx+(A-(A/B)*B)y
= Ay+B(x-(A/B)y)
則 x0=y,y0=(x-(A/B)y)。
好,推好式子再回到題目。
為了省去一些復雜的分類討論,我們把A,B都搞成非負整數,同事區間範圍也要改動。
然後判斷幾個特殊情況:
A==0&&B==0——>ans=(rx-lx+1)*(ry-ly+1)*(C==0)
A==0——>ans=(rx-lx+1)*jug(C/B in [ly..ry])*(C%B==0)
B==0——>ans=(ry-ly+1)*jug(C/A in [lx..rx])*(C%A==0)
然後,就是一般情況。
我們知道,AB同號時,x增加時,y減少,x減少時y增加。
我們設在做exgcd的時候得到的一組解為X,Y。
那麽,如果X<lx||Y>ry,那麽,我們要把他們都移進合法區間內。然後得到最極端的解。然後算出另一邊的極端解,然後處理一下細節。
如果X>rx||Y<ly,也差不多。
如果原來X,Y就都在合法範圍內,我們可以先把某一個處理得不合法,再做上面的工作。
具體怎麽算極端解,我真的沒法講清楚,細節非常多。。
還有這種題要盡量避免分類討論。。
code:
1 #include<bits/stdc++.h> 2 #define LL long long 3 using namespace std; 4 LL A,B,C,lx,rx,ly,ry,X,Y,gcd,delx,dely; 5 LL sx,sy,tx,ty,del,x[2],y[2],ans,kx,ky,k; 6 LL exgcd(LL A,LL B,LL &x,LL &y) { 7 if (!B) {x=1; y=0; return A;} 8 LL g=exgcd(B,A%B,x,y); 9 LL x0=y,y0=x-y*(A/B); 10 x=x0; y=y0; return g; 11 } 12 bool range_xy(LL x,LL y) {return x>=lx&&x<=rx&&y>=ly&&y<=ry;} 13 int main() { 14 int T; cin>>T; 15 for (int ts=1; ts<=T; ts++) { 16 scanf("%lld%lld%lld",&A,&B,&C); 17 scanf("%lld%lld%lld%lld",&lx,&rx,&ly,&ry); 18 19 if (A<0) A=-A,lx=-lx,rx=-rx,swap(lx,rx); 20 if (B<0) B=-B,ly=-ly,ry=-ry,swap(ly,ry); 21 C=-C; 22 if (A==0&&B==0) { 23 printf("Case %d: %lld\n",ts,(rx-lx+1)*(ry-ly+1)*(C==0)); continue; 24 } 25 26 gcd=exgcd(A,B,X,Y); 27 if (C%gcd!=0) {printf("Case %d: %lld\n",ts,0); continue;} 28 X=X*C/gcd,Y=Y*C/gcd; 29 delx=B/gcd,dely=A/gcd,ans=0; 30 31 if (delx==0) { 32 if (C%A!=0) ans=0; else sx=C/A,ans=(ry-ly+1)*range_xy(sx,ly); 33 printf("Case %d: %lld\n",ts,ans); continue; 34 }else 35 if (dely==0) { 36 if (C%B!=0) ans=0; else sy=C/B,ans=(rx-lx+1)*range_xy(lx,sy); 37 printf("Case %d: %lld\n",ts,ans); continue; 38 } 39 40 sx=X,sy=Y; 41 if (sx>=lx) { 42 k=(sx-lx)/delx+1; 43 sx=sx-k*delx,sy=sy+k*dely; 44 } 45 if (sx<lx||sy>ry) { 46 if ((lx-sx)%delx==0) kx=(lx-sx)/delx; else kx=(lx-sx)/delx+1; 47 if ((sy-ry)%dely==0) ky=(sy-ry)/dely; else ky=(sy-ry)/dely+1; 48 k=max(kx,ky); 49 sx+=delx*k,sy-=dely*k; 50 if (sx>rx||sy<ly) ans=0; 51 else { 52 kx=(rx-sx)/delx; 53 ky=(sy-ly)/dely; 54 k=min(kx,ky); 55 tx=sx+k*delx,ty=sy-k*dely; 56 ans=min((tx-sx)/delx+1,(sy-ty)/dely+1); 57 } 58 }else 59 if (sx>rx||sy<ly) { 60 if ((sx-rx)%delx==0) kx=(sx-rx)/delx; else kx=(sx-rx)/delx+1; 61 if ((ly-sy)%dely==0) ky=(ly-sy)/dely; else ky=(ly-sy)/dely+1; 62 k=max(kx,ky); 63 sx-=delx*k,sy+=dely*k; 64 if (sx<lx||sy>ry) ans=0; 65 else{ 66 kx=(sx-lx)/delx; 67 ky=(ry-sy)/dely; 68 k=min(kx,ky); 69 tx=sx-k*delx,ty=sy+k*dely; 70 ans=min((sx-tx)/delx+1,(ty-sy)/dely+1); 71 } 72 }else if (!range_xy) ans=0; 73 printf("Case %d: %lld\n",ts,ans); 74 } 75 return 0; 76 }View Code
[lightoj P1306] Solutions to an Equation