Time Limit: 2 second(s) | Memory Limit: 32 MB |
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 | Output for 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 | Case 1: 3 Case 2: 37 Case 3: 1 Case 4: 2 Case 5: 1 |
首先我们可以求出ax+by=gcd(a,b)=g的一个组解(x0,y0).而要使ax+by=c有解,必须有c%g==0.
继而可以得到ax+by=c的一个组解x1=c*x0/g , y1=c*y0/g。
这样可以得到ax+by=c的通解为: x=x1+b*t;y=y1-a*t;
#include <algorithm>
#include <string.h>
#include <iostream>
#include <stdio.h>
#include <string>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long LL;
const int N = 1e5+10;
LL mint(LL x,LL y)
{
return x<=y?x:y;
}
LL maxt(LL x,LL y)
{
return x>=y?x:y;
}
LL exgcd(LL a,LL b,LL &x,LL &y)
{
if(b==0)
{
x=1, y=0;
return a;
}
LL ans=exgcd(b,a%b,x,y);
LL tmp=x;
x=y;
y=tmp-a/b*y;
return ans;
}
LL abs1(LL a)
{
return a>=0?a:-a;
}
LL F(LL x)
{
if(x==0) return 0;
if(x>0) return 1;
else return -1;
}
int main()
{
int t, ncase=1;
scanf("%d", &t);
while(t--)
{
LL a, b, c, ax1,ax2, ay1, ay2;
scanf("%lld %lld %lld %lld %lld %lld %lld", &a, &b, &c, &ax1, &ax2, &ay1, &ay2);
printf("Case %d: ",ncase++);
if(a==0&&b==0)
{
if(c==0) printf("%lld\n",(ay2-ay1+1)*(ax2-ax1+1));
else printf("0\n");
continue;
}
else if(a==0)
{
if(c%b!=0) printf("0\n");
else
{
LL z=-c/b;
if(z>=ay1&&z<=ay2) printf("%lld\n",(ax2-ax1+1));
else printf("0\n");
}
continue;
}
else if(b==0)
{
LL z=-c/a;
if(c%a!=0) printf("0\n");
else if(z>=ax1&&z<=ax2) printf("%lld\n",(ay2-ay1+1));
else printf("0\n");
continue;
}
LL x, y;
LL g=exgcd(a,b,x,y);
if(c%g!=0) printf("0\n");
else//加和减没有区别因为都可以改变k的值得到,注意处理不等式乘以负数的符号变换,公式中的b为b/gcd(a,b)因为这样可以扩大k值
{
LL k1, k2, k3, k4;
if(b*g<0) swap(ax1,ax2);
k1=(ax1*g+c*x)/b;
if((ax1*g+c*x)% b!=0 && F(ax1*g+c*x)*F(b) > 0) k1+=1;
k2=(ax2*g+c*x)/b;
if((ax2*g+c*x)% (b)!=0 && F(ax2*g+c*x)*F(b) < 0) k2-=1;
if(-a*g<0) swap(ay1,ay2);
k3=(ay1*g+c*y)/(-a);
if((ay1*g+c*y)%(-a)!=0 && F(ay1*g+c*y)*F(-a)>0) k3+=1;
k4=(ay2*g+c*y)/(-a);
if((ay2*g+c*y)%(-a)!=0 && F(ay2*g+c*y)*F(-a)<0) k4-=1;
if(k3>k2||k4<k1) printf("0\n");
else printf("%lld\n",mint(k2,k4)-maxt(k1,k3)+1);
}
}
return 0;
}