【题解】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;
}