扩展欧几里得,给两个点,就可以求出直线方程为 (yy-y)*x0 + (x-xx)*y0 = x*yy - y*xx,求的是在线段上的整点个数。所以就是(yy-y)*10*x0 + (x-xx)*10*y0 = x*yy - y*xx满足条件的解的个数。用exgcd搞之后求出一个解,再求出在线段上第一个整点的位置,然后再求有多少个在线段上的点。
exgcd有点忘了,还有就是特殊情况的判断(比如平行坐标轴),另外就是不能交换输入点,输入
1.0 0.3 0.3 10.0交换后就是0.3 0.3 1.0 10.0就变成有整点了,下次一定要注意,多想想
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdio> 5 #include<cmath> 6 #include<string> 7 #include<algorithm> 8 9 using namespace std; 10 #define inf 0x3f3f3f3f 11 #define eps 1e-8 12 #define LL long long 13 #define ull unsigned long long 14 #define mnx 1005 15 16 void exgcd( LL a, LL b, LL &d, LL &x, LL &y ){ 17 if( !b ) { 18 d = a, x = 1, y = 0; // d恰好是最大公约数 19 } 20 else { 21 exgcd( b, a%b, d, y, x ); 22 y -= x*(a/b); 23 } 24 } 25 double ax, ay, bx, by; 26 void solve(){ 27 if( ax > bx ) swap( ax, bx ); 28 if( ay > by ) swap( ay, by ); 29 LL x = ax * 10, y = ay * 10, xx = bx * 10, yy = by * 10; 30 if( x == xx || y == yy ){ 31 if( x == xx ) swap( ax, ay ), swap( bx, by ), swap( x, y ), swap( xx, yy ); 32 if( yy % 10 ){ 33 puts( "0" ); return ; 34 } 35 x = ceil( ax ) * 10, xx = floor( bx ) * 10; 36 cout << x << " " << xx << endl; 37 if( xx < x ){ 38 puts( "0" ); return ; 39 } 40 printf( "%lld ", (xx-x)/10 + 1LL ); return ; 41 } 42 LL a = ( yy - y ) * 10, b = ( x - xx ) * 10, c = x * yy - y * xx, d, x0, y0; 43 //cout << a << " "<< b <<endl; 44 exgcd( a, b, d, x0, y0 ); 45 //cout <<c <<" " << d << endl; 46 if( c % d ){ 47 puts( "0" ); return ; 48 } 49 x = ceil( ax ), xx = floor( bx ); 50 y = ceil( ay ), yy = floor( by ); 51 //cout << 1 << endl; 52 if( x > xx || y > yy ){ 53 puts( "0" ); return ; 54 } 55 x0 = x0 * ( c / d ); 56 //cout << x0 << endl; 57 b /= d; 58 if( b < 0 ) b = -b; 59 x0 = x0 - ( x0 - x ) / b * b; 60 x0 -= b; 61 while( x0 < x ) x0 += b; 62 LL ans = ( xx - x0 ) / b; 63 while( x0 + ans * b <= xx ) ans++; 64 printf( "%lld ", ans ); 65 } 66 int main(){ 67 int cas; 68 scanf( "%d", &cas ); 69 while( cas-- ){ 70 scanf( "%lf%lf%lf%lf", &ax, &ay, &bx, &by ); 71 solve(); 72 } 73 return 0; 74 }