记
f(k)
表示
k
的素因子个数,
求
g(1)+…+g(n)
。
n≤1012
g(k)
的组合意义为满足
(i,j)=1
且
ij=k
的对数。
所以变成求
(i,j)=1
且
ij≤n
的对数。
∑ij≤n[(i,j)=1]===∑ij≤n∑d|i d|jμ(d)∑d=1n√μ(d)∑ij≤⌊nd2⌋1∑d=1n√μ(d)∑i=1⌊nd2⌋⌊nd2i⌋
复杂度 O(n√lnn)
#include<cstdio>
#include<cstdlib>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn=1000000;
const int P=1e9+7;
int prime[maxn+5],vst[maxn+5],num;
int miu[maxn+5];
inline void Pre(int n){
miu[1]=1;
for (int i=2;i<=n;i++){
if (!vst[i]) prime[++num]=i,miu[i]=-1;
for (int j=1;j<=num && (ll)i*prime[j]<=n;j++){
vst[i*prime[j]]=1;
if (i%prime[j]==0){
miu[i*prime[j]]=0; break;
}
miu[i*prime[j]]=-miu[i];
}
}
}
inline ll calc(ll n){
ll ret=0; ll l,r;
for (l=1;l*l<=n;l++) ret+=n/l;
for (ll t=n/l;l<=n;l=r+1,t--)
r=n/t,ret+=(r-l+1)*t%P;
return ret%P;
}
inline ll Solve(ll n){
ll ret=0;
for (int i=1;(ll)i*i<=n;i++)
if (miu[i])
ret+=miu[i]==1?calc(n/i/i):P-calc(n/i/i);
return ret%P;
}
int main(){
int T,Case=0; ll n;
freopen("t.in","r",stdin);
freopen("t.out","w",stdout);
scanf("%d",&T); Pre(maxn);
while (T--){
scanf("%I64d",&n);
printf("Case #%d: %I64d\n",++Case,Solve(n));
}
return 0;
}