SGU106 Extend GCD

    题意:给出方程ax + by + c = 0,以及a,b,c,x1,x2,y1,y2, 问有多少整数解(x,y)满足x1<=x<=x2,y1<=y<=y2。

    Problem:There is an equation ax + by + c = 0. Given a,b,c,x1,x2,y1,y2 you must determine, how many integer roots of this equation are satisfy to the following conditions:x1<=x<=x2,y1<=y<=y2. Integer root of this equation is a pair of integer numbers (x,y).

    解法:细节较多要注意。首先处理a,b全零,以及有一个零的情况。对于一般情况,用扩展GCD求出方程ax + by = gcd(a,b)的特解和a,b的gcd。如果题目有解,显然c能整除gcd。之后求出x,y的取值范围。具体方法是,先将特解x,y扩大倍数到匹配参数c,之后利用a,b除去gcd后的互质数对,算出可取区间。

    Solution:There are many details need to pay attention. First solving the case when a and b are 0, then a or b is 0. For general, using extend gcd to get the particular solution of ax + by = gcd(a,b) and gcd(a,b). If the problem has a solution, c must be divisible by gcd. After that calculate the range of x and y. Specifically, multiplying x and y to match parameter c, then utilizing the pair of numbers which come from (a,b) divides gcd, to make the range.

#include <iostream>
#include <stdio.h>
#include <cstring>
using namespace std;
typedef long long LL;
LL a,b,c,x1,x2,y1,y2,x,y,ans,tmp;
LL exgcd(LL a,LL b,LL &x,LL &y) {
    if (b==0) {
       x = 1;
       y = 0;
       return a; 
    }
    LL d = exgcd(b,a%b,x,y);
    LL xt = x;
    x = y;
    y = xt-a/b*y;
    return d;
}
int main() {
    cin >> a >> b >> c >> x1 >> x2 >> y1 >> y2;
    ans = 0;
    if (a==0 && b==0) {  
       if (c==0) ans = (x2-x1+1) * (y2-y1+1);
    }  
    else if (a==0 && b!=0) {  
         if (c % b==0) {  
            tmp = -c/b;  
            if (tmp>=y1 && tmp<=y2) ans = x2-x1+1;
         }  
    }
    else if (a!=0 && b==0) {  
         if (c % a==0) {  
            tmp = -c/a;  
            if (tmp>=x1 && tmp<=x2) ans = y2-y1+1;  
         }  
    } 
    else {
         LL gcd = exgcd(a,b,x,y);
         if (c%gcd==0) {
            LL k = -c/gcd;
            x = k*x;
            y = k*y;
            LL aa = b/gcd;
            LL bb = a/gcd; 
            LL lx = (x1 <= x || (x1 - x) % aa == 0) ? ((x1 - x) / aa) : ((x1 - x) / aa + 1);
            LL rx = (x2 >= x || (x2 - x) % aa == 0) ? ((x2 - x) / aa) : ((x2 - x) / aa - 1);
            LL ly = (y1 <= y || (y - y1) % bb == 0) ? ((y - y1) / bb) : ((y - y1) / bb - 1);
            LL ry = (y2 >= y || (y - y2) % bb == 0) ? ((y - y2) / bb) : ((y - y2) / bb + 1);
            if (lx > rx) swap(lx, rx);
            if (ly > ry) swap(ly, ry);
            if (ry >= lx && rx >= ly)
               ans = min(rx, ry) - max(lx, ly) + 1;
         }
    }
    cout << ans << endl;
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值