2018牛客网暑假ACM多校训练赛(第十场)H Rikka with Ants 类欧几里德算法

原文链接https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-H.html

题目传送门 - https://www.nowcoder.com/acm/contest/148/H

题意

  有两只蚂蚁在一个二维平面上走。一开始,他们都在点 $(1,0)$ 的位置。

  Rikka 布置了三条规定:

  1. 第一只蚂蚁不能走过直线 $y=cfrac{a}{b} x$ 。

  2. 第二只蚂蚁不能走过直线 $y=cfrac{c}{d} y$ 。

  3. 所有蚂蚁都不能走过直线 $y=0$ 。

  每一只蚂蚁的行走方式都是一样的,即:如果能往上走,那么向上;否则向右。

  问这两只蚂蚁走过的路径上有多少个整点是重合的,如果答案为 $infty$ ,输出 $-1$ 。

  多组数据,$Tleq 10^5,0leq a,b,c,d leq 10^9$ 。

题解

upd(2018-08-28): 无意中发现我之前那个 上界 的取值写错了,40多个阅读居然没人指出QAQ……

  首先,判掉无穷的情况:即斜率相同。

  然后,强制 $y=cfrac ab x$ 的斜率比 $y=cfrac cd x$ 大。(即,如果小了就交换)

  记 $f(x)=y_1=cfrac ab x,g(x)=y_2=cfrac cd x$ ,

  因此,对于一个点 $x$ ,必然有 $y_1>y_2$ 。于是,重合的整点中,横坐标为 $x$ 的点的 $y$ 坐标必然 $leq y_2$ 。又由于 $f(x-1)>g(x-1)$ ,所以,横坐标为 $x$ 的重合的整点的 $y$ 坐标必然 $geqleftlfloor cfrac{a(x-1)}{b} ight floor$ 。

  于是,答案就是:

$$egin{eqnarray*}&sum_{x=0}^{infty} maxleft(0,leftlfloorcfrac{c(x+1)}{d} ight floor-leftlfloorcfrac{ax-b}{b} ight floor ight)\=&sum_{x=0}^{infty} maxleft(0,leftlfloorcfrac{c(x+1)}{d} ight floor-leftlfloorcfrac{ax}{b} ight floor+1 ight)end{eqnarray*}$$

  我们考虑取一个上界,来从公式中拿掉那个 $max$ 。

  我们考虑到:

  如果我们取尽量大的 $i$ ,使得

$$cfrac {ai}{b} leq cfrac{c(i+1)}{d} +1$$

  则,对于 $x>i$,显然有:

$$leftlfloorcfrac{c(x+1)}{d} ight floor-leftlfloorcfrac{ax}{b} ight floor+1leq 0$$

  相反,对于 $x<i$ ,有:

$$leftlfloorcfrac{c(x+1)}{d} ight floor-leftlfloorcfrac{ax}{b} ight floor+1geq 0$$

  这两个容易证明。

  那么我们就可以解得上界为 $i=leftlfloor cfrac{(c+d)b}{ad-bc} ight floor$ ,于是,我们可以把原式写成:

$$egin{eqnarray*}&&sum_{x=0}^{infty} maxleft(0,leftlfloorcfrac{c(x+1)}{d} ight floor-leftlfloorcfrac{ax-b}{b} ight floor ight)\&=&sum_{x=0}^{infty} maxleft(0,leftlfloorcfrac{c(x+1)}{d} ight floor-leftlfloorcfrac{ax}{b} ight floor+1 ight)\&=&sum_{x=0}^{i}left(leftlfloorcfrac{c(x+1)}{d} ight floor-leftlfloorcfrac{ax}{b} ight floor+1 ight)\&=&sum_{x=0}^{i}leftlfloorcfrac{c(x+1)}{d} ight floor-sum_{x=0}^{i}leftlfloorcfrac{ax}{b} ight floor +i+1end{eqnarray*}$$

  上面前两个 $sum$ 是裸的类欧,直接拖一份写就可以了。

代码

#include <bits/stdc++.h>
using namespace std;
const int mod=998244353;
typedef long long LL;
typedef __int128 LLL;
LL f(LL a,LL b,LL c,LL n){
	if (a==0)
		return (b/c)%mod*((n+1)%mod)%mod;
	if (a>=c||b>=c)
		return ((LL)((LLL)a/c%mod*(n*(n+1)/2%mod))%mod
					+(b/c)*(n+1)%mod+f(a%c,b%c,c,n))%mod;
	LL tmp=((LLL)a*n+b)/c;
	return (tmp%mod*n%mod-f(c,c-b-1,a,tmp-1)+mod)%mod;
}
LL T,a,b,c,d;
void write(LLL x){
	if (x<0){
		putchar('-');
		x=-x;
	} 
	if (x>9)
		write(x/10);
	putchar('0'+x%10);
}
LL calc(LL x){
	return (f(c,c,d,x)-f(a,0,b,x)+x+1+mod)%mod;
}
int main(){
	scanf("%lld",&T);
	while (T--){
		scanf("%lld%lld%lld%lld",&a,&b,&c,&d);
		if (a*d==b*c){
			puts("-1");
			continue;
		}
		if (a*d<b*c)
			swap(a,c),swap(b,d);
		printf("%lld
",calc((c+d)*b/(d*a-c*b)));
	}
	return 0;
}

  

原文地址:https://www.cnblogs.com/zhouzhendong/p/NowCoder-2018-Summer-Round10-H.html