ARC123E Training

会 F 写不来 E 了属于是……

题意

给定 \(a,b,c,d,n\) ,令 \(f(x)=a+\lfloor\frac{x}{b}\rfloor,f(x)=c+\lfloor\frac{x}{d}\rfloor\) ,求 \(\sum_{i=1}^n[f(x)=g(x)]\)

\(T\) 组询问。 \((1\le T\le2\times10^5,1\le a,b,c,d,n\le10^6)\)

题解

数论大讨论水平仍然不行!!!

首先不考虑下取整这个条件,那么答案只会在 \(|f(x)-g(x)|\le1\) 中。

先找到这个区间的两个端点,并将这个区间于 \(f(x)=g(x)\) 处断开,对两边分别讨论,此处不写一些关于区间开闭的细节了。

现在重新考虑要下取整的 \(f\)\(g\) 了,不妨设在此段区间内 \(f(x)\ge g(x)\)

其实 \(\sum_{i=l}^r a+\lfloor\frac{x}{b}\rfloor\)\(\sum_{i=l}^r c+\lfloor\frac{x}{d}\rfloor\) 是容易算出来的,考虑这两个东西的差。

显然,这两者的差为多少,那么 \(f(x)>g(x)\) 的地方就有多少,又因为 \(f(x)-g(x)\le1\) ,所以容易算出 \(f(x)=g(x)\)\(x\) 个数。

单次询问 \(O(1)\)

代码:

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
ll sum(ll a,ll b) {ll n=a/b;return n*(n-1)/2*b+(a-b*n)*n;}
ll calc(ll l,ll r,ll a,ll b) {return a*(r-l)+sum(r,b)-sum(l,b);}
ll solve(){
	ll n,a,b,c,d,l,r,ans=0;
	scanf("%lld%lld%lld%lld%lld",&n,&a,&b,&c,&d);
	if(b==d) return a==c?n:0;
	if(b>d) swap(a,c),swap(b,d);
	l=max(0ll,b*d*(c-a-1)/(d-b))+1;
	r=min(n,b*d*(c-a)/(d-b))+1;
	if(l<r) ans=r-l-calc(l,r,c,d)+calc(l,r,a,b);
	l=max(0ll,b*d*(c-a)/(d-b))+1;
	r=min(n,b*d*(c-a+1)/(d-b))+1;
	if(l<r) ans+=r-l-calc(l,r,a,b)+calc(l,r,c,d);
	return ans;
}
signed main(){
	int t;scanf("%d",&t);
	while(t--) printf("%lld\n",solve());
	return 0;
}

ARC123E Training

上一篇:5 款阿里常用代码检测工具,免费用!


下一篇:同一份代码怎能在不同环境表现不同?记一个可选链因为代码压缩造成的bug