【分析】
显然 (oldsymbol f) 为积性函数,且 (oldsymbol f(p)=poplus 1=oldsymbol varphi(p)cdot 3^{[2mid p]})
令 (oldsymbol g(p)=oldsymbol varphi(p)cdot 3^{[2mid p]}) 且 (oldsymbol f=oldsymbol g*oldsymbol h) ,则:
(egin{aligned} oldsymbol f(p^k)&=sum_{i=0}^koldsymbol h(p^i)oldsymbol g(p^{k-i}) \\ oldsymbol f(p^k)&=sum_{i=1}^{k-1}oldsymbol h(p^i)oldsymbol g(p^{k-i})+oldsymbol h(p^k)+oldsymbol g(p^k) \\ oldsymbol h(p^k)&=oldsymbol f(p^k)-oldsymbol g(p^k)-sum_{i=1}^{k-1}oldsymbol h(p^i)oldsymbol g(p^{k-i}) end{aligned})
则 (p>2) 时:
(egin{aligned} oldsymbol h(p^k)&=(poplus k)-p^{k-1}(p-1)-sum_{i=1}^{k-1}oldsymbol h(p^i)cdot p^{k-i-1}cdot (p-1) \\oldsymbol h(p^{k-1})&=(poplus k-1)-p^{k-2}(p-1)-sum_{i=1}^{k-2}oldsymbol h(p^i)cdot p^{k-i-2}cdot (p-1) \\oldsymbol h(p^k)-poldsymbol h(p^{k-1})&=(poplus k)-p(poplus k-1)-oldsymbol h(p^{k-1})cdot (p-1) \\oldsymbol h(p^k)&=oldsymbol h(p^{k-1})+(poplus k)-p(poplus k-1) end{aligned})
而 (p=2) 时:
(egin{aligned} oldsymbol h(p^k)&=(poplus k)-3p^{k-1}(p-1)-sum_{i=1}^{k-1}oldsymbol h(p^i)cdot 3p^{k-i-1}cdot (p-1) \\oldsymbol h(p^{k-1})&=(poplus k-1)-3p^{k-2}(p-1)-sum_{i=1}^{k-2}oldsymbol h(p^i)cdot 3p^{k-i-2}cdot (p-1) \\oldsymbol h(p^k)-poldsymbol h(p^{k-1})&=(poplus k)-p(poplus k-1)-oldsymbol h(p^{k-1})cdot 3(p-1) \\oldsymbol h(2^k)-2oldsymbol h(2^{k-1})&=(2oplus k)-2(2oplus k-1)-3oldsymbol h(2^{k-1}) \\oldsymbol h(2^k)&=-oldsymbol h(2^{k-1})+(2oplus k)-2(2oplus k-1) end{aligned})
而由于 (oldsymbol varphi(p)cdot 3^{[2mid p]}=oldsymbol f(p)=oldsymbol h(p)+oldsymbol g(p)=oldsymbol h(p)+oldsymbol varphi(p)cdot 3^{[2mid p]}) 得到 (oldsymbol h(p)=0)
从而根据上述式子 (k>1) 时,(oldsymbol h(p^k)) 可以由 (oldsymbol h(p^{k-1})) 递推得到
我们定义 Powerful Number 为所有质因子均出现大于 (1) 次的数,以集合语言来讲,则是 (PN={n|forall (p_imid n) o (p_i^2mid n), p_iin Prime})
则不难发现,(oldsymbol h(n)=0, n otin PN) 且所有 Powerful Number 均可写为 (a^2b^3(a, bin Z_+)) 的形式
而 (n) 范围内,Powerful Number 的数量级为 (displaystyle sum_{a=1}^{sqrt n} sum_{b=1}^{sqrt[3] {nover a^2}}1=int_1^{sqrt n} ext daint_1^{sqrt[3]{nover a^2}} ext db=O(sqrt n))
(egin{aligned} sum_{i=1}^noldsymbol f(i)&=sum_{i=1}^nsum_{dmid i}oldsymbol h(d)cdot oldsymbol g({iover d}) \\&=sum_{d=1}^noldsymbol h(d)cdot sum_{i=1}^{n/d}oldsymbol g(i) \\&=sum_{d in PN}oldsymbol h(d)cdot G(n/d)&& ext{(}oldsymbol h ext{ 仅在 }PN ext{ 处有值 } ext{)} end{aligned})
只要预处理 (sqrt n) 范围内的质数,然后跑 dfs 即可在 (O(sqrt n)) 时间内枚举所有 Powerful Number
先问题化为对于 (G(n)) 如何求解
(egin{aligned} G(n)&=sum_{i=1}^n3^{[2mid i]}oldsymbol varphi(i) \\&=sum_{i=1}^n oldsymbol varphi(i)+2sum_{i=1}^n[2mid i]oldsymbol varphi(i) \\&=Phi(n)+2sum_{i=1}^{n/2}oldsymbol varphi(2i) \\&=Phi(n)+2S(n/2) \\ \\S(n)&=sum_{i=1}^n oldsymbol varphi(2i) \\&=sum_{i=1}^n oldsymbol varphi(i)+sum_{i=1}^n[2mid i]oldsymbol (i) \\&=Phi(n)+S(n/2) \\&=Phi(n)+Phi(n/2)+Phi(n/4)+Phi(n/8)+cdots&& ext{(}迭代 ext{)} \\ \\G(n)&=Phi(n)+2[Phi(n/2)+Phi(n/4)+Phi(n/8)+cdots] \\&=2[Phi(n)+Phi(n/2)+Phi(n/4)+Phi(n/8)+cdots]-Phi(n) end{aligned})
而 (oldsymbol varphi*oldsymbol I=oldsymbol {id}) 得:
(displaystyle {n(n+1)over 2}=sum_{i=1}^noldsymbol {id}(i)=sum_{i=1}^nsum_{dmid i}oldsymbol varphi({iover d})=sum_{d=1}^nPhi(n/d))
变型得到 (displaystyle Phi(n)={n(n+1)over 2}-sum_{d=2}^nPhi(n/d)) ,可由杜教筛在 (O(n^{2over 3})) 时间内预处理得到
总时间复杂度为杜教筛的预处理时间 (O(n^{2over 3})+) 杜教筛的运行时间 (O(n^{2over 3})+) 迭代 (G(n)) 的时间 (O(sqrt nlog n)+) PN 筛的时间 (O(sqrt n))
总复杂度为 (O(n^{2over 3}+sqrt nlog n))
【代码】
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<ll, ll> pii;
typedef double db;
#define fi first
#define se second
const int Lim=5e6, MAXN=Lim+10, P=1e9+7;
int fc[MAXN], prime[MAXN/10], cntprime, sphi[MAXN];
inline void sieve() {
for(int i=2; i<=Lim; ++i) {
if(!fc[i]) {
prime[++cntprime]=i;
fc[i]=i;
sphi[i]=i-1;
}
for(int j=1; j<=cntprime; ++j)
if(prime[j]*i>Lim) break;
else if(prime[j]<fc[i]) {
fc[prime[j]*i]=prime[j];
sphi[ prime[j]*i ]=sphi[ prime[j] ]*sphi[i];
}
else{
fc[prime[j]*i]=prime[j];
sphi[ prime[j]*i ]=prime[j]*sphi[i];
break;
}
}
sphi[1]=1;
for(int i=2; i<=Lim; ++i) {
sphi[i]+=sphi[i-1];
if(sphi[i]>=P) sphi[i]-=P;
}
}
struct Dusieve{
ll n, val[MAXN];
int Sphi[MAXN], G[MAXN];
int sqr, id1[MAXN], id2[MAXN], cntid;
inline int getid(ll val) { return val<=sqr?id1[val]:id2[n/val]; }
inline int query(ll n) { return G[getid(n)]; }
inline void init(ll n_) {
n=n_;
cntid=0;
sqr=sqrt(n)+0.5;
for(ll l=1, r, d; l<=n; l=r+1) {
r=n/(val[++cntid]=d=n/l);
if(d>sqr) id2[n/d]=cntid;
else id1[d]=cntid;
}
}
inline void work() {
for(int i=cntid; i>=1; --i) {
if(val[i]<=Lim) {
Sphi[i]=sphi[ val[i] ];
continue;
}
ll v=val[i];
int &res=Sphi[i];
res=(v%P); res=(ll)res*(res+1)%P*(P+1>>1)%P;
for(ll l=2, r, d; l<=v; l=r+1) {
r=v/(d=v/l);
res-=(r-l+1)*Sphi[getid(d)]%P;
if(res<0) res+=P;
}
}
for(int i=cntid; i>=1; --i) {
int &res=G[i];
ll v=val[i];
while(v) {
res+=Sphi[getid(v)];
if(res>=P) res-=P;
v>>=1;
}
res=(res*2%P-Sphi[i]+P)%P;
}
}
}ds;
inline int ans(ll n, int flr, int hn) {
int res=(ll)hn*ds.query(n)%P;
for(int i=flr+1; i<=cntprime; ++i) {
int p=prime[i], k=1;
ll val=n/p, newhn=0;
if(val<p) break;
while(val>=p) {
val/=p; ++k;
if(p==2) newhn=(-newhn+(k^2)-2*(k-1^2));
else newhn=newhn+(p^k)-(ll)p*(p^k-1);
newhn=((newhn%=P)<0?newhn+P:newhn);
res+=ans(val, i, (ll)hn*newhn%P);
if(res>=P) res-=P;
}
}
return res;
}
ll n;
int main(){
ios::sync_with_stdio(0);
cin.tie(0); cout.tie(0);
sieve();
cin>>n;
ds.init(n);
ds.work();
cout<<ans(n, 0, 1);
cout.flush();
return 0;
}