LOJ #124. 除數函數求和 1


 

題目描述

$\sigma_k(n) = \sum_{d | n} d ^ k$

求 $\sum_{i=1}^n\sigma_k(i)$ 的值對 109 取模的結果。

 

輸入格式

第一行兩個正整數 n,k

 

輸出格式

第一行輸出答案。

 

樣例

輸入樣例

5 2

輸出樣例

63

 

數據范圍與提示

對於 100% 的數據,1≤n,k≤1077​​ 。

 

 

Solution:

  本題ZYYS。。。

  直接枚舉顯然不行,我們考慮改為求$n$的某一因子$d$在整個函數中的貢獻是多少。

  套上數論分塊的思想,一個因子$d$對式子的貢獻是$\lfloor{\frac{n}{d}}\rfloor\times d^k$。

  這樣我們需要處理的就是$d^k$,直接$O(n\log k)$快速冪求出每個因子的冪是肯定不行的,因為$n$是$10^7$,直接會T。

  那么還是考慮優化,我們發現,每個數都能唯一分解,而在求冪時會有重復計算的質因子冪。於是,我們考慮線篩,這樣就可以用每個數的最小質因子冪去算它的冪了,那么整個過程只會對$n\leq 10^7$內的質數進行快速冪,最后復雜度就成了$\sqrt n \log k$,完全可行。

  所以最后就只需再$O(n)$掃一遍因子累加貢獻求和就好了。

代碼:

 

#include<iostream>
#define il inline
#define ll long long
#define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++)
#define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--)
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)>(b)?(b):(a))

using namespace std;
const int N=1e7,mod=1e9+7;
int prime[N+5],ans,cnt,n,k,sum[N+5];
bool isprime[N+5];

il int fast(ll s,ll k){
    ll ans=1;
    while(k){
        if(k&1)ans=ans*s%mod;
        k>>=1;
        s=s*s%mod;
    }
    return ans;
}

il void init(){
    sum[1]=1;
    For(i,2,n+1) {
        if(!isprime[i]) prime[++cnt]=i,sum[i]=fast(i,k);
        for(int j=1;j<=cnt&&prime[j]*i<=n+1;j++){
            isprime[prime[j]*i]=1;
            sum[prime[j]*i]=sum[i]*1ll*sum[prime[j]]%mod;
            if(i%prime[j]==0)break;
        }
    }
}

int main(){
    ios::sync_with_stdio(0);
    cin>>n>>k;
    init();
    For(i,1,n) ans=(ans+1ll*(n/i)*sum[i])%mod;
    cout<<ans;
    return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM