Description
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). |
Input
Input contains integer numbers a,b,c,x1,x2,y1,y2 delimited by spaces and line breaks. All numbers are not greater than 108 by absolute value。
Output
Write answer to the output.
Sample Input
1 1 -3 0 4 0 4
Sample Output
4
题意:
求出 ax+by=-c中的解 x y 符合 x1<=x<=x2 y1<=y<=y2 的解的个数
自己真的挺难理解这个的..然后参考了两个博客
都写的很详细. 直接贴出来去看吧..我感觉自己没这个水平去讲这个
http://blog.youkuaiyun.com/volzkzg/article/details/7427233
http://www.cnblogs.com/Rinyo/archive/2012/11/25/2787419.html
主要用到了扩展欧几里德算法 变形一下, 这些博客里面都有说道
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<string>
#include<algorithm>
#include<queue>
#include<stack>
#include<set>
#include<map>
#include<vector>
using namespace std;
long long gcd(long long a,long long b)
{
return b==0?a:gcd(b,a%b);
}
long long exgcd(long long a,long long b,long long &x,long long &y)
{
if (!b)
{
x=1;
y=0;
return a;
}
long long gcd=exgcd(b,a%b,x,y);
long long temp=x;
x=y;
y=temp-a/b*y;
return gcd;
}
long long upper(long long a,long long b)//往上取整
{
if (a<=0)
return a/b;
return (a-1)/b+1;
}
long long lower(long long a,long long b)//往下取整
{
if (a>=0)
return a/b;
return (a+1)/b-1;
}
long long get(long long l,long long r,long long d,long long &k1,long long &k2)
{
if (d<0)
{
l=-l;
r=-r;
d=-d;
swap(l,r);
}
k1=upper(l,d);
k2=lower(r,d);
}
int main()
{
long long a,b,c,x1,y1,x2,y2;
while (cin>>a>>b>>c)//ax+by+c=0 >>ax+by=-c
{
bool flag=0;
c=-c;
cin>>x1>>x2>>y1>>y2;
long long ans,x,y;
if (!a && !b && !c)
{
cout<<(x2-x1+1)*(y2-y1+1)<<endl;
continue;
}
else if (!a && !b)
{
cout<<0<<endl;
continue;
}
else if (!a)
{
if (c%b || c/b<y1 || c/b>y2)
ans=0;
else
ans=x2-x1+1;
cout<<ans<<endl;
continue;
}
else if (!b)
{
if (c%a || c/a<x1 || c/a>x2)
ans=0;
else
ans=y2-y1+1;
cout<<ans<<endl;
continue;
}
/*
先处理了a,b,c为0的情况
*/
long long g=gcd(a,b);
if (c%g)//如果 c不是gcd(a,b)的倍数 无解
{
cout<<0<<endl;
continue;
}
/*
网上的解释:
方程两边同时除以gcd(a,b).我们假设aa=a/gcd(a,b),bb=b/gcd(a,b),nn=n/gcd(a,b)
所以方程两边同时除以gcd(a,b)后,
可以得到一个方程aa*x+bb*y=nn.
并且该方程aa*x+bb*y=nn的解x,y就是a*x+b*y=n的解
我们只要求解出aa*x+bb*y=1的其中一个解,设这两个解为x0,y0.
那么aa*x+bb*y=nn的其中一个解解就是x0*nn,y0*nn.
接着,a*x+b*y=n的其中一个解解也就是x0*nn,y0*nn.
a*(x0*nn)+b*(y0*nn)=n.
我们会发现
a*(x0*nn+1*b)+b*(y0*nn-1*a)=n
a*(x0*nn-1*b)+b*(y0*nn+1*a)=n.
继续推广
a*(x0*nn+k*b)+b*(y0*nn-k*a)=n (k属于整数)
nn=n/gcd(a,b).
x=x0*nn+k*b
y=y0*nn-k*a
*/
a/=g;
b/=g;
c/=g;// c=c/g 上面已经将c变为-c
exgcd(a,b,x,y);
long long k1,k2,k3,k4;
x*=c;
y*=c;
get(x1-x,x2-x,b,k1,k2);
get(y1-y,y2-y,-a,k3,k4);
// cout<<x<<" "<<y<<endl;
ans=min(k2,k4)-max(k1,k3)+1;
cout<<ans<<endl;
}
return 0;
}