Description
二维平面上有两只蚂蚁初始在(1,0)(1,0)(1,0)点,有三条直线:
1.y=01.y=01.y=0,没有蚂蚁可以越过这条线
2.y=abx(a,b>0)2.y=\frac{a}{b}x(a,b>0)2.y=bax(a,b>0),只有第二只蚂蚁可以越过这条线
3.y=cdx(c,d>0)3.y=\frac{c}{d}x(c,d>0)3.y=dcx(c,d>0),只有第一只蚂蚁可以越过这条线
注意到蚂蚁只能往上走和往右走,且如果蚂蚁可以往上走就先往上走,不能往上走了再往右走,故两只蚂蚁的路径唯一,问被两只蚂蚁均经过的整点个数
Input
第一行一整数TTT表示用例组数,每组用例输入四个整数a,b,c,da,b,c,da,b,c,d
(1≤T≤105,1≤a,b,c,d≤109)(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,否则输出整点个数,结果模998244353998244353998244353
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
显然若两条直线重合则两只蚂蚁均经过的整点有无穷个,假设ab>cd\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≤abxy≤cdxy+1>ab(x−1)y+1>cd(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)
由ab>cd\frac{a}{b}>\frac{c}{d}ba>dc知只需满足2,32,32,3式即可,问题转化为求y=cdxy=\frac{c}{d}xy=dcx和y+1=ab(x−1)y+1=\frac{a}{b}(x-1)y+1=ba(x−1)与xxx轴围成三角形中整点的个数(不包括原点以及y+1=ab(x−1)y+1=\frac{a}{b}(x-1)y+1=ba(x−1)上的整点),这显然是有穷个点,假设两条直线内整点横坐标最大值为XXX,则轻易得到
X=⌊(a+b)dad−bc⌋
X=\lfloor\frac{(a+b)d}{ad-bc}\rfloor
X=⌊ad−bc(a+b)d⌋
那么我们只要求出y=cdxy=\frac{c}{d}xy=dcx在x∈[1,X]x\in [1,X]x∈[1,X]范围内与xxx轴围成整点的个数,再减去y+1=ab(x−1)y+1=\frac{a}{b}(x-1)y+1=ba(x−1)在x∈[1,X]x\in [1,X]x∈[1,X]范围内与xxx轴围成的纵坐标非负的整点个数即为答案
对于第一部分,显然有
X+∑x=1X⌊cxd⌋
X+\sum\limits_{x=1}^X\lfloor\frac{cx}{d}\rfloor
X+x=1∑X⌊dcx⌋
对于第二部分,先把直线向左平移一个单位,然后想上平移一个答案,则第二部分答案等价于y=abxy=\frac{a}{b}xy=bax在x∈[0,X−1]x\in [0,X-1]x∈[0,X−1]范围内与xxx轴围成的纵坐标为正的整点个数,也即为
∑x=0X−1⌊axb⌋
\sum\limits_{x=0}^{X-1}\lfloor\frac{ax}{b}\rfloor
x=0∑X−1⌊bax⌋
令f(a,b,c,n)=∑x=0n⌊ax+bc⌋f(a,b,c,n)=\sum\limits_{x=0}^n\lfloor\frac{ax+b}{c}\rfloorf(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),只要求出fff即可
1.若a=0a=0a=0,则显然f(a,b,c,n)=(n+1)⋅⌊bc⌋f(a,b,c,n)=(n+1)\cdot \lfloor\frac{b}{c}\rfloorf(a,b,c,n)=(n+1)⋅⌊cb⌋
2.若a,ba,ba,b不全小于ccc,那么把这个下取整的两块整数拿出来,也即
⌊ax+bc⌋=⌊ac⌋⋅x+⌊bc⌋+⌊(a%c)⋅x+b%cc⌋
\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⋅⌊ac⌋+(n+1)⋅⌊bc⌋
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<c0<a<c,0\le b<c0<a<c,0≤b<c,回到该式的几何意义,即为直线y=ax+bcy=\frac{ax+b}{c}y=cax+b在x∈[0,n]x\in [0,n]x∈[0,n]范围内与xxx轴围成的区域中纵坐标为正的整点个数,由于bc<1\frac{b}{c}<1cb<1,故该范围没有横坐标x=0x=0x=0的整点,记该区域整点纵坐标最大值为mmm,则有
m=⌊an+bc⌋
m=\lfloor\frac{an+b}{c}\rfloor
m=⌊can+b⌋
对于[1,n]×[1,m][1,n]\times [1,m][1,n]×[1,m]范围内的nmnmnm个整点,不合法整点为直线y=ax+bcy=\frac{ax+b}{c}y=cax+b与yyy轴围成的、横坐标为正且不在直线上的整点,这些整点也即为y=ax+b−1cy=\frac{ax+b-1}{c}y=cax+b−1与yyy轴围成的横坐标为正的整点个数,交换两个坐标轴即为y=cx−b−1ay=\frac{cx-b-1}{a}y=acx−b−1与xxx轴在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)=nm−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)
递归求解即可,注意在计算mmm时,ananan可能会爆long longlong\ longlong long,要用__int128\_\_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;
}