题目地址
- 题目大意:
给定 n , k n,k n,k,求下面式子的值(对 2 64 2^{64} 264取模)
∑ i = 1 n σ 0 ( i k ) \sum_{i=1}^n\sigma_{0}(i^k) i=1∑nσ0(ik)
其中 σ 0 \sigma_{0} σ0是约数个数函数。
n , k ≤ 1 0 10 n,k\leq 10^{10} n,k≤1010
这个似乎可以用杜教筛之类的,但是比较麻烦,复杂度比较高,但如果用 m i n _ 25 min\_25 min_25就比较容易了。
我们只用考虑对于质数时的取值:
σ 0 ( p k ) = k + 1 \sigma_0(p^k)=k+1 σ0(pk)=k+1
然后直接套min_25的式子就好啦!
#include<cmath>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define ll unsigned long long
using namespace std;
const int M=2e6+10;
ll cnt,ID,n,sq,K;
ll idx(ll a){return a<=sq?a:ID-(n/a)+1;}
ll A[M],prime[M],g[M];
ll S(ll a,ll b){
if(a<prime[b]) return 0;
ll ans=g[idx(a)]-(K+1ll)*(b-1ll);
for(ll i=b;i<=cnt&&prime[i]*prime[i]<=a;i++){
for(ll j=prime[i],k=K+1ll;j*prime[i]<=a;j*=prime[i],k+=K){
ans+=S(a/j,i+1)*k+(k+K);
}
}
return ans;
}
int T;
int main(){
for(scanf("%d",&T);T--;){
scanf("%llu%llu",&n,&K);
if(n==1){puts("1");continue;}
sq=(ll)sqrt(n);ID=cnt=0;
for(ll i=1;i<=n;i=A[ID]+1){
A[++ID]=n/(n/i);
g[ID]=(K+1ll)*(A[ID]-1ll);
}
for(ll i=2;i<=sq;i++)if(g[i]!=g[i-1]){
prime[++cnt]=i;
for(ll j=ID,down=i*i;A[j]>=down;j--){
g[j]-=g[idx(A[j]/i)]-(K+1ll)*(cnt-1ll);
}
}
printf("%llu\n",S(n,1)+1ll);
}
return 0;
}