LOJ #124. 除数函数求和 1 题解
题目大意
定义 \(\sigma_k(n)=\sum\limits_{d|n}d^k\),求 \(\sum\limits_{i=1}^n\sigma_k(i)\)。其中 \(n,k\leq 10^7\)。
分析
我们不需要知道 \(\sigma_k(n)\) 是否是积性函数,因为我们只需要求他的前缀和。
\[\begin{aligned}\sum_{i=1}^n\sigma_k(i)&=\sum_{d=1}^nd^k\sum_{i=1}^n[d|i]\\&=\sum_{d=1}^nd^k\lfloor\frac{n}{d}\rfloor\end{aligned}
\]
于是欢乐地线筛一遍 \(d^k\) 然后欢乐地线性模拟一遍就好力。
代码
#include<bits/stdc++.h>
#define HohleFeuerwerke using namespace std
#pragma GCC optimize(3,"Ofast","-funroll-loops","-fdelete-null-pointer-checks")
#pragma GCC target("ssse3","sse3","sse2","sse","avx2","avx")
#define int long long
HohleFeuerwerke;
inline int read(){
int s=0,f=1;char c=getchar();
for(;!isdigit(c);c=getchar()) if(c=='-') f=-1;
for(;isdigit(c);c=getchar()) s=s*10+c-'0';
return s*f;
}
inline void write(int x){
if(x<0) putchar('-'),x=-x;
if(x>=10) write(x/10);
putchar('0'+x%10);
}
const int MOD=1e9+7,MAXN=1e7+5;
int n,k,ans;
int f[MAXN],tot,sum[MAXN],pri[MAXN];
bitset<MAXN> ispri;
inline int ksm(int a,int b){
if(b==0) return 1;
else if(b%2==1) return a*ksm(a,b-1)%MOD;
else{
int tmp=ksm(a,b/2);
return tmp*tmp%MOD;
}
}
inline void init(){
f[1]=1,ispri[1]=1;
for(int i=1;i<=n;i++){
if(!ispri[i]) f[i]=ksm(i,k),pri[++tot]=i;
for(int j=1;j<=tot&&i*pri[j]<=n;j++){
ispri[i*pri[j]]=1;
f[i*pri[j]]=(f[i]*f[pri[j]])%MOD;
if(!i%pri[j]) break;
}
}
}
signed main()
{
n=read(),k=read(); init();
for(int i=1;i<=n;i++) ans=(ans+f[i]*(n/i))%MOD;
write(ans); puts("");
}

LOJ #124. 除数函数求和 1 题解
浙公网安备 33010602011771号