• Floor and Mod(CF1485C)(数论)


    题意:
    问多少对 (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;
    }
    
    
    越自律,越自由
  • 相关阅读:
    Asp.Net基础 9.Web开发原则
    JavaScript – 1.事件 + 2.变量 + 3.判断变量初始化 + 4.函数的声明 + 5.匿名函数
    DOM – 3.window对象的属性
    Dom – 1.window对象事件 + 2.body、document对象的事件
    faint
    开会
    it's over
    so funny
    no topic
    震惊:有良医生揭无良献血内幕!
  • 原文地址:https://www.cnblogs.com/ha-chuochuo/p/14403581.html
Copyright © 2020-2023  润新知