Newcoder 148 H.Rikka with Ants(计算几何+递归)

85 篇文章 0 订阅
18 篇文章 0 订阅

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) (1T105,1a,b,c,d109)

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,y1)往上走到达 ( x , y ) (x,y) (x,y)点,要么从 ( x − 1 , y ) (x-1,y) (x1,y)点无法到达 ( x − 1 , y + 1 ) (x-1,y+1) (x1,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. ybaxydcxy+1>ba(x1)y+1>dc(x1)
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(x1) x x x轴围成三角形中整点的个数(不包括原点以及 y + 1 = a b ( x − 1 ) y+1=\frac{a}{b}(x-1) y+1=ba(x1)上的整点),这显然是有穷个点,假设两条直线内整点横坐标最大值为 X X X,则轻易得到
X = ⌊ ( a + b ) d a d − b c ⌋ X=\lfloor\frac{(a+b)d}{ad-bc}\rfloor X=adbc(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(x1) 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=1Xdcx
对于第二部分,先把直线向左平移一个单位,然后想上平移一个答案,则第二部分答案等价于 y = a b x y=\frac{a}{b}x y=bax x ∈ [ 0 , X − 1 ] x\in [0,X-1] x[0,X1]范围内与 x x x轴围成的纵坐标为正的整点个数,也即为
∑ x = 0 X − 1 ⌊ a x b ⌋ \sum\limits_{x=0}^{X-1}\lfloor\frac{ax}{b}\rfloor x=0X1bax
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=0ncax+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,X1),只要求出 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=cax+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 &lt; a &lt; c , 0 ≤ b &lt; c 0&lt;a&lt;c,0\le b&lt;c 0<a<c,0b<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 &lt; 1 \frac{b}{c}&lt;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+b1 y y y轴围成的横坐标为正的整点个数,交换两个坐标轴即为 y = c x − b − 1 a y=\frac{cx-b-1}{a} y=acxb1 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,cb1,a,m1),故此时有
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)=nmf(c,cb1,a,m1)
递归求解即可,注意在计算 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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值