【Exgcd】解的个数

Description

  已知x,y满足如下条件:
  ax+by+c=0 ; x1 <= x <= x2 ; y1 <= y <= y2 ; x,y均为整数。
  其中:a,b,c,x1,x2,y1,y2 都是绝对值不超过 10^8 的整数。
  求(x,y)的解的个数。

Input

  第一行:n  说明:有 n 个任务。n<=10。之后有 n 行,每行为:a,b,c,x1,x2,y1,y2

Output

  有n行,第i行是第i个任务的结果。

Sample Input 1 

2
2 3 -7 0 10 0 10
1 1 1 -10 10 -9 9

Sample Output 1

1
19

Hint

-100000000 <= a,b,c,x1,x2,y1,y2 <= 100000000

扩欧例题。
求范围中解的个数时用通解 列不等式:
x1 <= x0+k*b/gcd <= x2
y1 <= x0-k*a/gcd <= y2
变形可得到两个关于k的区间,求交集包含的整点个数即可
#include<bits/stdc++.h>
#define lowbit(x) (x&(-x))
#define mst(a, b) memset(a, b, sizeof(a))
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
LL read() {
    LL o=0, f=1;
    char ch;
    while(!isdigit(ch=getchar())) if(ch == '-') f=-1;
    while(isdigit(ch)) o=o*10+ch-'0', ch = getchar();
    return o*f;
}

const int maxn = 100005, maxm = 500005;

LL Exgcd(LL a, LL b, LL &x, LL &y) {
    if(b == 0) { x=1, y=0; return a; }
    LL gcd = Exgcd(b, a%b, y, x);
    y = y-a/b*x;
    return gcd;
}

int len(double a, double b, double c, double d) { // 求[a,b],[c,d]交集含整点个数 
    a = ceil(a), c = ceil(c), b = floor(b), d = floor(d);
    return max((int)((min(b, d)-max(a, c)))+1, 0);
}

LL a, b, c, d, x, y, X, Y;
inline bool inRangex(LL n) { return x<=n && n<=X; }
inline bool inRangey(LL n) { return y<=n && n<=Y; }

int main() {
    LL n = read();
    while(n--) {
        a=read(), b=read(), c=read(), x=read(), X=read(), y=read(), Y=read();
        if(x>X || y>Y) { puts("0"); continue; }
        c = -c; // ax+by=c
        //a, b, c都要进行非负处理orz
        if(c<0) c=-c, a=-a, b=-b;
        if(a<0) a=-a, swap(x=-x, X=-X);
        if(b<0) b=-b, swap(y=-y, Y=-Y);
        if(!a && !b) {
            printf("%lld\n", c ? 0 : (LL)(X-x+1)*(Y-y+1));
        }
        else if(!a) {
            if(c%b != 0 || !inRangey(c/b)) puts("0");
            else printf("%d\n", X-x+1);
        }
        else if(!b) {
            if(c%a != 0 || !inRangex(c/a)) puts("0");
            else printf("%d\n", Y-y+1);
        }
        else {
            LL x0, y0;
            LL gcd = Exgcd(a, b, x0, y0);
            if(c%gcd != 0) { puts("0"); continue; }
            a/=gcd, b/=gcd, c/=gcd;
            x0 *= c, y0 *= c;
            printf("%d\n", len(1.0*(x-x0)/b, 1.0*(X-x0)/b, 1.0*(y0-Y)/a, 1.0*(y0-y)/a));
        }
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/de-compass/p/12209276.html
今日推荐