Floor and Mod(CF1485C)(数论)

题意:
问多少对 \(a,b\) 满足 \(\lfloor \frac{a}{b} \rfloor =a\ mod\ b\)
其中 \(1\leqslant a\leqslant x,1\leqslant b\leqslant y\)


想法:

  • \(\lfloor \frac{a}{b} \rfloor =a\ mod\ b\) 如果对于 \(a\) 没有限制的话,对于每个 \(b\) 那么答案就是 \(b-1\) 个 ( \(0\sim (b-1)\) 只有 \(0\) 不符合。
  • 考虑对于一个 \(b\) 确定,哪些 \(a\) 会满足答案。如 \(\frac{b+1}{b}、\frac{2\times (b+1)}{b}...\)都满足,那么就可以得到 $\frac{k\times (b+1)}{b} = (k\times (b+1))\ mod\ b $ 满足。
  • 由于 \(k\times (b+1)\) 的取值范围是 \(1\sim x\),那么对于每个 \(b\),在这个取值范围内可取答案数量就是 \(\lfloor \frac{x}{b+1} \rfloor\)
  • 所以最终答案就是
    .
    \(\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;
}

posted @ 2021-02-15 13:32  hachuochuo  阅读(166)  评论(0编辑  收藏  举报