杜教筛
我会第一问!
因为当 i i i中有平方因子时 μ ( i ) = 0 \mu(i)=0 μ(i)=0,所以第一问的答案就是 1 1 1。
第二问有 φ ( i 2 ) = i ⋅ φ ( i ) \varphi(i^2)=i\cdot\varphi(i) φ(i2)=i⋅φ(i)。因为 φ ( i ) = i ∏ ( 1 − 1 p i ) \varphi(i)=i\prod(1-\frac1{p_i}) φ(i)=i∏(1−pi1),乘上 i i i后质因子并没有变,所以直接乘 i i i。
那么就是求 ∑ i ⋅ φ ( i ) \sum i\cdot\varphi(i) ∑i⋅φ(i),而 φ ∗ 1 = I d \varphi*1=Id φ∗1=Id。所以我们设 g ( i ) = 1 g(i)=1 g(i)=1,由杜教筛的结论, S ( n ) = ∑ i 2 − ∑ i = 2 n S ( ⌊ n i ⌋ ) S(n)=\sum i^2-\sum_{i=2}^nS(\lfloor\frac ni\rfloor) S(n)=∑i2−∑i=2nS(⌊in⌋)。除法分块递归做就好了。
然鹅 n ≤ 1 e 9 n\leq 1e9 n≤1e9,要用map记录答案。然鹅map太慢了,要预处理 n ≤ 1 e 9 2 / 3 = 1 e 6 n\leq 1e9^{2/3}=1e6 n≤1e92/3=1e6的答案。这样时间复杂度是 n 2 / 3 n^{2/3} n2/3的,我也不知道为什么。
代码:
#include<map>
#include<cstdio>
#include<algorithm>
#define N 100001
using namespace std;
typedef long long LL;
const LL iv6=166666668;
LL n,P=1e9+7,phi[N],p[N]; bool f[N]; map <LL,LL> s;
inline void Make(){
phi[1]=1;
for (LL i=2;i<N;i++){
if (!f[i]) p[++p[0]]=i,phi[i]=i-1;
for (int j=1,v;j<=p[0]&&i*p[j]<N;j++){
f[v=i*p[j]]=true;
if (i%p[j]==0){ phi[v]=phi[i]*p[j]; break; }
phi[v]=phi[i]*phi[p[j]];
}
}
for (LL i=2;i<N;i++) phi[i]=(phi[i]*i%P+phi[i-1])%P;
}
LL calc(LL n){
if (n<N) return phi[n]; if (s.count(n)) return s[n];
LL ans=n*(n+1)%P*(n*2+1)%P*iv6%P;
for (LL l=2,r;l<=n;l=r+1)
r=n/(n/l),(ans-=(l+r)*(r-l+1)/2%P*calc(n/l)%P+P)%=P;
return s[n]=(ans+P)%P;
}
int main(){ return scanf("%lld",&n),puts("1"),Make(),printf("%lld\n",calc(n)),0; }