考虑一个数 \(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;
}