codevs1213 解的个数

codevs1213 解的个数

题目描述 Description

已知整数x,y满足如下面的条件:

ax+by+c = 0

p<=x<=q

r<=y<=s

求满足这些条件的x,y的个数。

输入描述 Input Description

第一行有一个整数n(n<=10),表示有n个任务。n<=10

以下有n行,每行有7个整数,分别为:a,b,c,p,q,r,s。均不超过108。

输出描述 Output Description

共n行,第i行是第i个任务的解的个数。

样例输入 Sample Input

2

2 3 -7 0 10 0 10

1 1 1 -10 10 -9 9

样例输出 Sample Output

1

19

代码

扩展欧几里得算法解方程的模板题。如果c%gcd(a,b)!=0,无解。先用扩展欧几里德算法求出 ax+by=gcd(a,b)的一个解,将他乘以 c/gcd(a,b) 就得到了原方程的一个解 x0,y0;

然后根据 x=x0+k*(b/gcd(a,b)),y=y0-k*(a/gcd(a,b)),可以直接暴力枚举出答案。也可以用公式计算。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
inline ll read(){
    ll x=0,f=1;char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
    return x*f;
}
ll a,b,c,d,p,q,r,s,T,x,y,ans;
void exgcd(ll a,ll b,ll &x,ll &y){
    if(!b){d=a; x=1;y=0;return;}
    exgcd(b,a%b,y,x); y-=(a/b)*x;
}
int main(){
    T=read();
    while(T--){
        a=read();b=read();c=-1ll*read();p=read();q=read();r=read();s=read();
        if(a==0&&b==0&&c!=0){printf("0\n");continue;}
        if(q<p||s<r){printf("0\n"); continue;}
        if(a==0&&b==0&&c==0){printf("%lld\n",(q-p+1)*(s-r+1));continue;}
        exgcd(a,b,x,y);  if(c%d){printf("0\n"); continue;}
        ans=0; ll x0=x*(c/d),y0=y*(c/d),b1=b/d,a1=a/d;
        for(ll i=-1000000;i<=1000000;++i){
            ll xx=x0+i*b1,yy=y0-i*a1;
            if(xx>=p&&xx<=q&&yy>=r&&yy<=s) ++ans;
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2017-11-07 09:41  沐灵_hh  阅读(428)  评论(0编辑  收藏  举报