标签:++ div view san eve its c++ style 分类
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, x2, y1, y2 (x1 ≤ x2, y1 ≤ y2). The value of each integer will lie in the range [-108, 108].
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 }
[lightoj P1306] Solutions to an Equation
标签:++ div view san eve its c++ style 分类
原文地址:http://www.cnblogs.com/whc200305/p/7739236.html