Educational Codeforces Round 5 E. Sum of Remainders【数学分块】

题目链接:https://codeforc.es/problemset/problem/616/E

题目大意:给定两个数n,mn,m,要求计算i=1mn%i\sum_{i=1}^mn\%i
思路:

i=1mn%i\sum_{i=1}^mn\%i=i=1mnnii\sum_{i=1}^mn-\lfloor{\frac{n}{i}}\rfloor*i=nmi=1mniin*m-\sum_{i=1}^m\lfloor{\frac{n}{i}}\rfloor*i

化简到这之后就可以用数学分块进行求和就okok了。

AC代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod=1e9+7;
ll qpow(ll x,ll y){
    ll ans=1;
    while(y){
        if(y&1){
            ans=ans*x%mod;
        }
        y>>=1;
        x=x*x%mod;
    }
    return ans;
}
ll ss(ll x,ll inv_2)
{
    return x%mod*((x+1)%mod)%mod*inv_2%mod;
}
int main()
{
    ll n,m;
    ll inv_2=qpow(2,mod-2);
    cin>>n>>m;
    ll sum1=n%mod*(m%mod)%mod;//计算第一部分
    ll l=1,r=1;
    ll sum2=0;
    ll i=1;
    ll minn=min(n,m);
    while(l<=minn){//分块求和
        ll tmp=n/l;
        r=min(n/max(1LL,tmp),minn);//注意右边界
        sum2=(sum2+tmp%mod*(ss(r,inv_2)-ss(l-1,inv_2)+mod)%mod)%mod;//sum2计算的是第二部分
        l=r+1;
    }
    ll ans=(sum1-sum2+mod)%mod;
    cout<<ans<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章