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("");
}
posted @ 2021-07-25 10:36  _HofFen  阅读(131)  评论(0)    收藏  举报