CF1780E Josuke and Complete Graph

考虑一个数 \(x\) 能够计入答案要满足什么条件,即存在一组 \(\gcd(a,b)=x\)。等价于 \(x|a,x|b,\gcd(\frac{a}{x},\frac{a}{x})=1\)

贪心的想要满足 \(l\le a,b\le r\),那么 \(a\) 取最小的满足能整除 \(x\) 的数即 \(l+x-(l\mod x)=l+x-(l-x\cdot \lfloor\frac{l}{x}\rfloor)=(\lfloor\frac{l}{x}\rfloor+1)\cdot x\)\(b\) 就取 \(a+x\),随意对于任意 \(x\),判断一下是否满足 \((\lfloor\frac{l}{x}\rfloor+2)\cdot x\le r\) 即可。

转化到这做法就显然了,整除分块。

但是注意一下每组的 \(R\) 需要特判一下,因为可能出现 \(l\mod R=0\) 的特殊情况,此时 \(a=\frac{l}{R}\cdot R\)

并且若这组中的数不完全满足条件,这个判断条件显然有单调性二分一下就好。

\(O(T\sqrt{n})\)

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define int ll
#define pii pair<int,int>
#define fi first
#define se second
#define mp make_pair
//const int N=,mod=1e9+7;
int calc(int x,int R){
	int l=1,r=1,res=0;
	while(l<=x){r=x/(x/l);res+=(x%r==0?(x/r+1)*r<=R:(x/r+2)*r<=R);
		if(r>1&&(x/(r-1)+2)*(r-1)<=R)res+=r-l;
		else if(r>1){
			int lf=l,rt=r-1,mid;
			while(lf<=rt)(mid=lf+rt>>1,(x/mid+2)*mid<=R?lf=mid+1:rt=mid-1);
			res+=lf-l;
		}l=r+1;
	}int lf=x+1,rt=R,mid;
	while(lf<=rt)(mid=lf+rt>>1,2*mid<=R?lf=mid+1:rt=mid-1);
	res+=lf-1-x;return res;
}
signed main(){
	ios::sync_with_stdio(false),
	cin.tie(0),cout.tie(0);
	int T;cin>>T;
	while(T--){
		int l,r;cin>>l>>r;
		cout<<calc(l,r)<<'\n';
	} 
	return 0;
}
posted @ 2025-11-04 11:03  Uesugi1  阅读(7)  评论(0)    收藏  举报