Description
二维平面上有两只蚂蚁初始在 ( 1 , 0 ) (1,0) (1,0)点,有三条直线:
1. y = 0 1.y=0 1.y=0,没有蚂蚁可以越过这条线
2. y = a b x ( a , b > 0 ) 2.y=\frac{a}{b}x(a,b>0) 2.y=bax(a,b>0),只有第二只蚂蚁可以越过这条线
3. y = c d x ( c , d > 0 ) 3.y=\frac{c}{d}x(c,d>0) 3.y=dcx(c,d>0),只有第一只蚂蚁可以越过这条线
注意到蚂蚁只能往上走和往右走,且如果蚂蚁可以往上走就先往上走,不能往上走了再往右走,故两只蚂蚁的路径唯一,问被两只蚂蚁均经过的整点个数
Input
第一行一整数 T T T表示用例组数,每组用例输入四个整数 a , b , c , d a,b,c,d a,b,c,d
( 1 ≤ T ≤ 1 0 5 , 1 ≤ a , b , c , d ≤ 1 0 9 ) (1\le T\le 10^5,1\le a,b,c,d\le 10^9) (1≤T≤105,1≤a,b,c,d≤109)
Output
如果两只蚂蚁均经过的整点有无限个则输出 − 1 -1 −1,否则输出整点个数,结果模 998244353 998244353 998244353
Sample Input
5
1 1 1 1
1 2 1 1
1 3 2 1
1 100 1 99
12 34 56 78
Sample Output
-1
2
1
5049
3
Solution
显然若两条直线重合则两只蚂蚁均经过的整点有无穷个,假设
a
b
>
c
d
\frac{a}{b}>\frac{c}{d}
ba>dc,两只蚂蚁若都经过
(
x
,
y
)
(x,y)
(x,y)点,那么蚂蚁要么从
(
x
,
y
−
1
)
(x,y-1)
(x,y−1)往上走到达
(
x
,
y
)
(x,y)
(x,y)点,要么从
(
x
−
1
,
y
)
(x-1,y)
(x−1,y)点无法到达
(
x
−
1
,
y
+
1
)
(x-1,y+1)
(x−1,y+1)点只能往右走到达
(
x
,
y
)
(x,y)
(x,y)点,故有
{
y
≤
a
b
x
y
≤
c
d
x
y
+
1
>
a
b
(
x
−
1
)
y
+
1
>
c
d
(
x
−
1
)
\left\{ \begin{array}{lcl} y\le \frac{a}{b}x\\ y\le \frac{c}{d}x\\ y+1>\frac{a}{b}(x-1)\\ y+1>\frac{c}{d}(x-1)\\ \end{array} \right.
⎩⎪⎪⎨⎪⎪⎧y≤baxy≤dcxy+1>ba(x−1)y+1>dc(x−1)
由
a
b
>
c
d
\frac{a}{b}>\frac{c}{d}
ba>dc知只需满足
2
,
3
2,3
2,3式即可,问题转化为求
y
=
c
d
x
y=\frac{c}{d}x
y=dcx和
y
+
1
=
a
b
(
x
−
1
)
y+1=\frac{a}{b}(x-1)
y+1=ba(x−1)与
x
x
x轴围成三角形中整点的个数(不包括原点以及
y
+
1
=
a
b
(
x
−
1
)
y+1=\frac{a}{b}(x-1)
y+1=ba(x−1)上的整点),这显然是有穷个点,假设两条直线内整点横坐标最大值为
X
X
X,则轻易得到
X
=
⌊
(
a
+
b
)
d
a
d
−
b
c
⌋
X=\lfloor\frac{(a+b)d}{ad-bc}\rfloor
X=⌊ad−bc(a+b)d⌋
那么我们只要求出
y
=
c
d
x
y=\frac{c}{d}x
y=dcx在
x
∈
[
1
,
X
]
x\in [1,X]
x∈[1,X]范围内与
x
x
x轴围成整点的个数,再减去
y
+
1
=
a
b
(
x
−
1
)
y+1=\frac{a}{b}(x-1)
y+1=ba(x−1)在
x
∈
[
1
,
X
]
x\in [1,X]
x∈[1,X]范围内与
x
x
x轴围成的纵坐标非负的整点个数即为答案
对于第一部分,显然有
X
+
∑
x
=
1
X
⌊
c
x
d
⌋
X+\sum\limits_{x=1}^X\lfloor\frac{cx}{d}\rfloor
X+x=1∑X⌊dcx⌋
对于第二部分,先把直线向左平移一个单位,然后想上平移一个答案,则第二部分答案等价于
y
=
a
b
x
y=\frac{a}{b}x
y=bax在
x
∈
[
0
,
X
−
1
]
x\in [0,X-1]
x∈[0,X−1]范围内与
x
x
x轴围成的纵坐标为正的整点个数,也即为
∑
x
=
0
X
−
1
⌊
a
x
b
⌋
\sum\limits_{x=0}^{X-1}\lfloor\frac{ax}{b}\rfloor
x=0∑X−1⌊bax⌋
令
f
(
a
,
b
,
c
,
n
)
=
∑
x
=
0
n
⌊
a
x
+
b
c
⌋
f(a,b,c,n)=\sum\limits_{x=0}^n\lfloor\frac{ax+b}{c}\rfloor
f(a,b,c,n)=x=0∑n⌊cax+b⌋,则所求答案为
X
+
f
(
c
,
0
,
d
,
X
)
−
f
(
a
,
0
,
b
,
X
−
1
)
X+f(c,0,d,X)-f(a,0,b,X-1)
X+f(c,0,d,X)−f(a,0,b,X−1),只要求出
f
f
f即可
1.若 a = 0 a=0 a=0,则显然 f ( a , b , c , n ) = ( n + 1 ) ⋅ ⌊ b c ⌋ f(a,b,c,n)=(n+1)\cdot \lfloor\frac{b}{c}\rfloor f(a,b,c,n)=(n+1)⋅⌊cb⌋
2.若
a
,
b
a,b
a,b不全小于
c
c
c,那么把这个下取整的两块整数拿出来,也即
⌊
a
x
+
b
c
⌋
=
⌊
a
c
⌋
⋅
x
+
⌊
b
c
⌋
+
⌊
(
a
%
c
)
⋅
x
+
b
%
c
c
⌋
\lfloor\frac{ax+b}{c}\rfloor=\lfloor\frac{a}{c}\rfloor \cdot x+\lfloor\frac{b}{c}\rfloor+\lfloor\frac{(a\%c)\cdot x+b\%c}{c}\rfloor
⌊cax+b⌋=⌊ca⌋⋅x+⌊cb⌋+⌊c(a%c)⋅x+b%c⌋
进而有
f
(
a
,
b
,
c
,
n
)
=
f
(
a
%
c
,
b
%
c
,
c
,
n
)
+
n
(
n
+
1
)
2
⋅
⌊
a
c
⌋
+
(
n
+
1
)
⋅
⌊
b
c
⌋
f(a,b,c,n)=f(a\%c,b\%c,c,n)+\frac{n(n+1)}{2}\cdot \lfloor\frac{a}{c}\rfloor+(n+1)\cdot \lfloor\frac{b}{c}\rfloor
f(a,b,c,n)=f(a%c,b%c,c,n)+2n(n+1)⋅⌊ca⌋+(n+1)⋅⌊cb⌋
3.若
0
<
a
<
c
,
0
≤
b
<
c
0<a<c,0\le b<c
0<a<c,0≤b<c,回到该式的几何意义,即为直线
y
=
a
x
+
b
c
y=\frac{ax+b}{c}
y=cax+b在
x
∈
[
0
,
n
]
x\in [0,n]
x∈[0,n]范围内与
x
x
x轴围成的区域中纵坐标为正的整点个数,由于
b
c
<
1
\frac{b}{c}<1
cb<1,故该范围没有横坐标
x
=
0
x=0
x=0的整点,记该区域整点纵坐标最大值为
m
m
m,则有
m
=
⌊
a
n
+
b
c
⌋
m=\lfloor\frac{an+b}{c}\rfloor
m=⌊can+b⌋
对于
[
1
,
n
]
×
[
1
,
m
]
[1,n]\times [1,m]
[1,n]×[1,m]范围内的
n
m
nm
nm个整点,不合法整点为直线
y
=
a
x
+
b
c
y=\frac{ax+b}{c}
y=cax+b与
y
y
y轴围成的、横坐标为正且不在直线上的整点,这些整点也即为
y
=
a
x
+
b
−
1
c
y=\frac{ax+b-1}{c}
y=cax+b−1与
y
y
y轴围成的横坐标为正的整点个数,交换两个坐标轴即为
y
=
c
x
−
b
−
1
a
y=\frac{cx-b-1}{a}
y=acx−b−1与
x
x
x轴在
x
∈
[
1
,
m
]
x\in [1,m]
x∈[1,m]范围内围成区域的纵坐标为正的整点个数,也即为
f
(
c
,
c
−
b
−
1
,
a
,
m
−
1
)
f(c,c-b-1,a,m-1)
f(c,c−b−1,a,m−1),故此时有
f
(
a
,
b
,
c
,
n
)
=
n
m
−
f
(
c
,
c
−
b
−
1
,
a
,
m
−
1
)
f(a,b,c,n)=nm-f(c,c-b-1,a,m-1)
f(a,b,c,n)=nm−f(c,c−b−1,a,m−1)
递归求解即可,注意在计算
m
m
m时,
a
n
an
an可能会爆
l
o
n
g
l
o
n
g
long\ long
long long,要用
_
_
i
n
t
128
\_\_int128
__int128
Code
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef __int128 lll;
#define mod 998244353
#define inv2 499122177
int mul(int x,int y)
{
ll z=1ll*x*y;
return z-z/mod*mod;
}
int add(int x,int y)
{
x+=y;
if(x>=mod)x-=mod;
return x;
}
int f(int a,int b,int c,ll n)
{
if(a==0)return mul((n+1)%mod,b/c);
if(a>=c||b>=c)
{
int res=mul(mul(mul(n%mod,(n+1)%mod),inv2),a/c);
res=add(res,mul((n+1)%mod,b/c));
return add(res,f(a%c,b%c,c,n));
}
ll m=((lll)a*n+b)/c;
return add(mul(n%mod,m%mod),mod-f(c,c-b-1,a,m-1));
}
int main()
{
int T,a,b,c,d;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d%d",&a,&b,&c,&d);
if(1ll*a*d==1ll*b*c)
{
printf("-1\n");
continue;
}
if(1ll*a*d<1ll*b*c)swap(a,c),swap(b,d);
ll x=(1ll*(b+a)*d)/(1ll*a*d-1ll*b*c);
int ans=add(add(x%mod,f(c,0,d,x)),mod-f(a,0,b,x-1));
printf("%d\n",ans);
}
return 0;
}