题目描述
输入格式
输出格式
样例
数据范围与提示
扫描二维码关注公众号,回复:
1759610 查看本文章
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)$扫一遍因子累加贡献求和就好了。
代码:
1 #include<iostream> 2 #define il inline 3 #define ll long long 4 #define For(i,a,b) for(int (i)=(a);(i)<=(b);(i)++) 5 #define Bor(i,a,b) for(int (i)=(b);(i)>=(a);(i)--) 6 #define Max(a,b) ((a)>(b)?(a):(b)) 7 #define Min(a,b) ((a)>(b)?(b):(a)) 8 9 using namespace std; 10 const int N=1e7,mod=1e9+7; 11 int prime[N+5],ans,cnt,n,k,sum[N+5]; 12 bool isprime[N+5]; 13 14 il int fast(ll s,ll k){ 15 ll ans=1; 16 while(k){ 17 if(k&1)ans=ans*s%mod; 18 k>>=1; 19 s=s*s%mod; 20 } 21 return ans; 22 } 23 24 il void init(){ 25 sum[1]=1; 26 For(i,2,n+1) { 27 if(!isprime[i]) prime[++cnt]=i,sum[i]=fast(i,k); 28 for(int j=1;j<=cnt&&prime[j]*i<=n+1;j++){ 29 isprime[prime[j]*i]=1; 30 sum[prime[j]*i]=sum[i]*1ll*sum[prime[j]]%mod; 31 if(i%prime[j]==0)break; 32 } 33 } 34 } 35 36 int main(){ 37 ios::sync_with_stdio(0); 38 cin>>n>>k; 39 init(); 40 For(i,1,n) ans=(ans+1ll*(n/i)*sum[i])%mod; 41 cout<<ans; 42 return 0; 43 }