Loading

【题解】ARC123E - Training

非常神的数论思维题。

将文字转化为数学语言,我们要求的是

\[\sum\limits_{i=1}^n [A_x+\left\lfloor\frac{i}{B_x}\right\rfloor=A_y+\left\lfloor\frac{i}{B_y}\right\rfloor] \]

显然,如果 \(B_x = B_y\),则答案等于 \([A_x =A_y]n\)

不失一般性,我们令 \(B_x < B_y\)​,然后观察等号两边的式子。

首先 \(A_x\)\(B_x\) 都是常数,我们只用考虑下取整函数。

由于 \(B_x\) 要小一点,所以左边增长会快一点。但是增长不是连续的。

令等式左边为 \(f(i)\),右边为 \(g(i)\),不难发现 \(f(i) - g(i)\) 相邻两项的差只可能是 \(\{-1,0,1\}\)。并且对于任意 \(i<j\),有 \(f(i)-g(i) - 1 \le f(j) + g(j)\)

所以我们可以二分出最前面的位置 \(l\) 使得 \(f(l) - g(l) = 0\),同理求出位置 \(p,r\) 满足 \(f(p) - g(p) = 1,f(r) - g(r) = 2\)

接下来就很清晰了,对于区间 \(i\in [l, p - 1]\)\(f(i) - g(i) \in \{0, -1\}\),同理若 \(i\in [p, r - 1],f(i) - g(i) \in\{0,1\}\)

对于这两个区间,我们只用分别求 \(\sum f(i)\)\(\sum g(i)\) 即可,这都可以 \(\mathcal{O}(1)\) 求。

时间复杂度 \(\mathcal{O}(T\log N)\)

#define int long long
int n;
int calc(int x,int y,int p){
	int l = 0, r = n / x, ed = r + 1;
	while(l <= r){
		int mid = (l + r) >> 1;
		if(mid - mid * x / y >= p)ed = mid, r = mid - 1;
		else l = mid + 1;
	}
	return ed * x;
}
int f(int x,int y){
	int g = x / y;
	int w = g * (g - 1) / 2 * y;
	return w + g * (x % y + 1);
}
int func(int l,int r,int a,int b){
	if(l > r)return 0;
	return (r - l + 1) * a + f(r, b) - f(l - 1, b);
}
void solve(){
	n = read();int ax = read(), bx = read(), ay = read(), by = read();
	if(bx == by){
		if(ax == ay)printf("%lld\n", n);
		else printf("0\n");
		return ;
	}
	if(bx > by)swap(ax, ay), swap(bx, by);
	if(ax > ay){printf("0\n");return ;}
	int p = calc(bx, by, ay - ax + 1LL);
	int l = calc(bx, by, ay - ax), r = calc(bx, by, ay - ax + 2);
	l = max(l, 1LL);
	if(l > n){printf("0\n");return ;}
	if(p > n){printf("%lld\n", n - l + 1 - func(l, n, ay, by) + func(l, n, ax, bx)); return ;}
	if(r > n)r = n + 1;
	printf("%lld\n", 
		p - l - func(l, p - 1, ay, by) + func(l, p - 1, ax, bx)
		+ r - p - func(p, r - 1, ax, bx) + func(p, r - 1, ay, by));
}

signed main() {
	int T = read();while(T--)solve();

	return 0;
}
posted @ 2021-11-11 23:02  7KByte  阅读(142)  评论(0编辑  收藏  举报