1. 程式人生 > >數論(擴充套件歐幾里得求方程整數解)

數論(擴充套件歐幾里得求方程整數解)

A - 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, 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

分析:

顯然用擴充套件歐幾里得求整數解,先貼一下大佬求解過程:

擴充套件歐幾里德演算法證明過程:

 如何求其他解;

 

還要注意用不等式求解時,要討論正負號,為負數時不等式方向會改變,同小取小,同大取大

同時還要注意a==0&&b==0,a==0&&b!=0,a!=0&&b==0這三種情況要單獨討論

AC code:

#include<iostream>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
void exgcd(ll a,ll b,ll& d,ll &x,ll &y)
{
    if(!b){
        d=a,x=1,y=0;
    }
    else
    {
        exgcd(b,a%b,d,y,x);
        y-=x*(a/b);
    }
}
int main()
{
    int t;
    cin>>t;
    ll a,b,c,x1,y1,x2,y2;
    int cas=0;
    while(t--)
    {
        ll x,y,gcd;
        cin>>a>>b>>c>>x1>>x2>>y1>>y2;
        c=-c;//變為擴充套件歐幾里得方程的形式
        cas++;
        cout<<"Case "<<cas<<": ";
        ll ans=0;
        ///單獨討論特殊情況
        if(a==0&&b==0)
        {
            if(c==0)
                cout<<(x2-x1+1)*(y2-y1+1)<<endl;
            else
                cout<<0<<endl;
            continue;
        }
        else if(a==0&&b!=0)
        {
            if(c%b==0)
            {
                ll tmp=c/b;
                if(y1<=tmp&&tmp<=y2)
                    ans=x2-x1+1;
            }
            cout<<ans<<endl;
            continue;
        }
        else if(a&&b==0)
        {
            if(c%a==0)
            {
                ll tmp=c/a;
                if(x1<=tmp&&tmp<=x2)
                    ans=y2-y1+1;
            }
            cout<<ans<<endl;
            continue;
        }
        exgcd(a,b,gcd,x,y);
        if(c%gcd)
        {
            cout<<0<<endl;
            continue;
        }///如果c不是gcd的倍數則無整數解
        ll x0=x*c/gcd;
        ll y0=y*c/gcd;
        ll b1=b/gcd;
        ll a1=a/gcd;
        ll tx1,tx2,ty1,ty2;
        if(b*gcd>=0)
          {
              tx1=ceil(1.0*(x1-x0)/b1);//左邊界向右取整
              tx2=floor(1.0*(x2-x0)/b1);//右邊界向左取整
          }
        else
        {
            tx1=ceil(1.0*(x2-x0)/b1);
            tx2=floor(1.0*(x1-x0)/b1);
        }
        if(a*gcd>=0)
        {
           ty1=ceil(1.0*(y0-y2)/a1);
           ty2=floor(1.0*(y0-y1)/a1);
        }
        else
        {
           ty1=ceil(1.0*(y0-y1)/a1);
           ty2=floor(1.0*(y0-y2)/a1);
        }
        ll l=max(tx1,ty1);
        ll r=min(tx2,ty2);
        if(l>r)
            cout<<0<<endl;
        else
            cout<<r-l+1<<endl;
    }
    return 0;
}