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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章