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 ");continue;} if(q<p||s<r){printf("0 "); continue;} if(a==0&&b==0&&c==0){printf("%lld ",(q-p+1)*(s-r+1));continue;} exgcd(a,b,x,y); if(c%d){printf("0 "); 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 ",ans); } return 0; }