[ARC123E] Training
多测,求值
\[\sum_{i=1}^{n}\Big[a+\lfloor\frac{i}{b}\rfloor=c+\lfloor\frac{i}{d}\rfloor\Big]
\]
\(1\le T\le 2\times 10^5\),\(1\le n\le 10^9\),\(1\le a,b,c,d\le 10^6\)。
没见过,还得是广附哥。
令 \(b\le d\),设 \(f(x)=a+\dfrac{x}{b}\),\(g(x)=c+\dfrac{x}{d}\),\(F(x)=\lfloor f(x)\rfloor\),\(G(x)=\lfloor g(x)\rfloor\)。
把下取整拆成不等式:\(\alpha-1<\lfloor\alpha\rfloor\le \alpha\),考虑函数 \(f(x)-g(x)\) 可能贡献的取值:
-
\(f(x)-g(x)\in(-1,0]\),\(F(x)-G(x)\in\{-1,0\}\)。
-
\(f(x)-g(x)\in(0,1]\),\(F(x)-G(x)\in\{0,1\}\)。
这两个区间可以二分得到。接下来考虑第一种情况,第二种同理。
求 \(\displaystyle \sum_{x=l}^{r}\Big[F(x)-G(x)=0\Big]\),由于 \(F(x)-G(x)\in\{-1,0\}\),对 \(F(x)-G(x)\) 求和,结果记为 \(k\),容易得到原式的值即 \(r-l+1+k\)。
求和可以做到 \(O(1)\),太闲了可以草个类欧上去。
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int read(){
int x=0,w=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')w=-1;ch=getchar();}
while(isdigit(ch))x=(x<<3)+(x<<1)+(ch^48),ch=getchar();
return x*w;
}
ll f(ll a,ll b,ll c,ll n){
if(n<0)return 0;
if(!a||!n)return (n+1)*(b/c);
ll A=a/c,B=b/c;
if(A||B)return n*(n+1)/2*A+B*(n+1)+f(a%c,b%c,c,n);
ll M=(a*n+b)/c;
return M*n-f(c,c-b-1,a,M-1);
}
ll calc(ll a,ll b,ll c,ll l,ll r){
return f(a,b,c,r)-f(a,b,c,l-1);
}
ll n,a,b,c,d;
void solve(){
n=read(),a=read(),b=read(),c=read(),d=read();
if(b>d)swap(a,c),swap(b,d);
ll l=1,r=n,mid;
ll p1=-1,p2=n+1,p3=-1;
while(l<=r){
mid=(l+r)>>1;
if(mid*(d-b)>b*d*(c-a-1))r=mid-1,p1=mid;
else l=mid+1;
}
if(p1==-1)return puts("0"),void();
l=p1,r=n;
while(l<=r){
mid=(l+r)>>1;
if(mid*(d-b)>b*d*(c-a))r=mid-1,p2=mid;
else l=mid+1;
}
l=p2,r=n;
while(l<=r){
mid=(l+r)>>1;
if(mid*(d-b)<=b*d*(c-a+1))l=mid+1,p3=mid;
else r=mid-1;
}
if(p3==-1)p3=p2-1;
ll ans=0,k=calc(1,c*d,d,p1,p2-1)-calc(1,a*b,b,p1,p2-1);
ans+=p2-p1-k;
k=calc(1,a*b,b,p2,p3)-calc(1,c*d,d,p2,p3);
ans+=p3-p2+1-k;
printf("%lld\n",ans);
}
int main(){
int T=read();
while(T--)solve();
return 0;
}