#杜教筛,欧拉函数#51nod 1227 平均最小公倍数
题目
设 \(\large A(n)=\frac{1}{n}\sum_{i=1}^n lcm(i,n)\),
求 \(\sum_{i=l}^rA(i)\),\(n\leq 10^9\)
分析
题意可以转化成求 \(\large \sum_{i=1}^n\frac{1}{i}\sum_{j=1}^i lcm(i,j)\)
首先把 \(lcm\) 弄掉就是 \(\large \sum_{i=1}^n\sum_{j=1}^i\frac{j}{\gcd(i,j)}\)
考虑枚举 \(\gcd(i,j)\) 那么再化简一下可以得到
\[\sum_{i=1}^n\sum_{d|i}\sum_{j=1}^{\frac{i}{d}}j[\gcd(\frac{i}{d},j)==1]=\sum_{i=1}^n\sum_{d|i}\sum_{j=1}^{d}j[\gcd(d,j)==1]
\]
设 \(\large f(n)=\sum_{i=1}^{n}j[\gcd(n,i)==1]\),那么 \(\large f(n)=\begin{cases}\frac{n\varphi(n)}{2}[n>1]\\1\end{cases}\)
那么原式进一步化简为 \(\large \frac{n}{2}+\frac{1}{2}\sum_{i=1}^n\sum_{d|i}d\varphi(d)\)
枚举 \(d\) 可以得到
\[\frac{n}{2}+\frac{1}{2}\sum_{d=1}^nd\varphi(d)\lfloor\frac{n}{d}\rfloor
\]
外层整除分块,然后里层卷一个 \(id\) 杜教筛就可以了
代码
#include <cstdio>
#include <unordered_map>
using namespace std;
const int N=10000011,mod=1000000007;
const long long i2=(mod+1)/2,i6=i2/3;
int f[N],prime[N],v[N],Cnt,A,B;
unordered_map<int,int>F;
int mo(int x,int y){return x+y>=mod?x+y-mod:x+y;}
void Pro(int n){
f[1]=v[1]=1;
for (int i=2;i<=n;++i){
if (!v[i]) prime[++Cnt]=v[i]=i,f[i]=i*(i-1ll)%mod;
for (int j=1;j<=Cnt&&prime[j]<=n/i;++j){
f[i*prime[j]]=1ll*f[i]*f[prime[j]]%mod,v[i*prime[j]]=1;
if (i%prime[j]==0){
f[i*prime[j]]=mo(f[i*prime[j]],1ll*f[i]*prime[j]%mod);
break;
}
}
}
for (int i=2;i<=n;++i) f[i]=mo(f[i],f[i-1]);
}
int phid(int n){
if (n<=N-11) return f[n];
if (F.find(n)!=F.end()) return F[n];
int ans=i6*n%mod*(n+1)%mod*(n<<1|1)%mod;
for (int l=2,r;l<=n;l=r+1)
r=n/(n/l),ans=mo(ans,mod-i2*(l+r)%mod*(r-l+1)%mod*phid(n/l)%mod);
return ans;
}
int answ(int n){
int ans=n,las=0;
for (int l=1,r,now;l<=n;l=r+1,las=now){
r=n/(n/l),now=phid(r);
ans=mo(ans,1ll*(now-las+mod)*(n/l)%mod);
}
return i2*ans%mod;
}
int main(){
Pro(N-11),scanf("%d%d",&A,&B);
return !printf("%d",mo(answ(B),mod-answ(A-1)));
}