题意:
问多少对 (a,b) 满足 (lfloor frac{a}{b}
floor =a mod b) 。
其中 (1leqslant aleqslant x,1leqslant bleqslant y) 。
想法:
- (lfloor frac{a}{b} floor =a mod b) 如果对于 (a) 没有限制的话,对于每个 (b) 那么答案就是 (b-1) 个 ( (0sim (b-1)) 只有 (0) 不符合。
- 考虑对于一个 (b) 确定,哪些 (a) 会满足答案。如 (frac{b+1}{b}、frac{2 imes (b+1)}{b}...)都满足,那么就可以得到 $frac{k imes (b+1)}{b} = (k imes (b+1)) mod b $ 满足。
- 由于 (k imes (b+1)) 的取值范围是 (1sim x),那么对于每个 (b),在这个取值范围内可取答案数量就是 (lfloor frac{x}{b+1} floor)。
- 所以最终答案就是
.(sum^{y}_{b=2} min(b-1,frac{x}{b+1} ))。 - 接下来考虑这个式子怎么求。把这个式子分成两部分,那么分界点就是 (b-1=frac{x}{b+1}) 时,也就是 $b=sqrt{x+1} $ 时,那么答案就是
.(sum^{sqrt{x+1}}_{b=2} b-1 +sum^{ y}_{b=sqrt{x+1}+1} frac{x}{b+1}) - 对于前半部分,就是等差数列求和。对于下半部分,考虑数论分块
- 需要注意的就是在分块的过程中区间选取时,对于 (b)的枚举不能超过 (x)且区间末端不能超过 (x,y)。
代码:
#include<bits/stdc++.h>
#define ll long long
using namespace std;
const int mod=1e9+7;
const int maxn=100005;
int main()
{
int T;
ll a,b;
cin>>T;
while(T--){
scanf("%lld%lld",&a,&b);
ll num=sqrt(a+1);
ll ans=0;
if(num>b){
num=b;
ans+=(num)*(num-1)/2;
}else{
ans+=(num)*(num-1)/2;
for(ll l=num+1,r;l<=min(a,b);l=r+1){
if(a/(l+1)==0)break;
else{
r=min(b,min(a,a/(a/(l+1))-1));
}
ans+=(r-l+1)*(a/(l+1));
}
}
cout<<ans<<endl;
}
return 0;
}