题目链接:https://ac.nowcoder.com/acm/contest/879/I
题目大意:
d为n的因数,那么[1, n]所有d的倍数都会加一次(d^k)
假设i^k为q[i]
所以结果为:
for(int i=1;i<=n;i++)
{
ans=(ans+q[i]*(n/i))%mod;
}
现在就是怎样快速求q[i], 因为幂函数为完全积性函数。所以我们可以用线性筛的思想求q[i],找到其中一个因子k,那么q[i]=q[k]*q[i/k];
//线性筛 筛i^k
void pre()
{
q[1]=1;
int d=0;
for(int i=2; i<=n; i++)
{
if(!vis[i])
{
pri[++cnt]=i;
q[i]=ksm(i,k);
}
for(int j=1; j<=cnt&&i*pri[j]<=n; j++)
{
vis[i*pri[j]]=1;
q[i*pri[j]]=1ll*q[i]*q[pri[j]]%mod;
if(i%pri[j]==0)
{
break;
}
}
}
}
也可以用埃式筛。
#include<bits/stdc++.h>
#define LL long long
const int mod=1e9+7;
using namespace std;
LL qpow(LL n,LL k){
LL res=1;
n=n%mod;
while(k){
if(k&1)res=res*n%mod;
n=n*n%mod;
k>>=1;
}
return res;
}
LL q[10000005]={0}, k;
void prime()
{
q[1]=1;
for(int i=2;i<=10000000;i++)
{
if(!q[i]){
q[i]=qpow(i,k);
for(int j=i+i;j<=10000000;j+=i){
q[j]=i;
}
}else{
q[i]=(q[q[i]]*q[i/q[i]])%mod;
}
}
}
int main()
{
LL n, ans=0;
scanf("%lld%lld",&n,&k);
prime();
for(int i=1;i<=n;i++)
{
ans=(ans+q[i]*(n/i))%mod;
}
printf("%lld\n",ans);
return 0;
}