51nod1227-平均最小公倍數【杜教篩,尤拉函式】
阿新 • • 發佈:2021-11-09
正題
題目連結:http://www.51nod.com/Challenge/Problem.html#problemId=1227
題目大意
定義
\[F(a)=\frac{\sum_{i=1}^a lcm(a,i)}{a} \]給出\(l,r\)求\(\sum_{i=l}^rF(i)\)
解題思路
好久沒做數論題了
直接拆成兩個字首和的差,然後有
函式\(H(n)=\varphi(n)n\)
code
#include<cstdio> #include<cstring> #include<algorithm> #include<map> #define ll long long using namespace std; const ll N=5e6,P=1e9+7; ll cnt,pri[N/10],phi[N]; bool v[N];map<ll,ll> mp; void Prime(){ phi[1]=1; for(ll i=2;i<N;i++){ if(!v[i])pri[++cnt]=i,phi[i]=i-1; for(ll j=1;j<=cnt&&i*pri[j]<N;j++){ v[i*pri[j]]=1; if(i%pri[j]==0){ phi[i*pri[j]]=phi[i]*pri[j]; break; } phi[i*pri[j]]=phi[i]*(pri[j]-1); } } for(ll i=1;i<N;i++) phi[i]=(phi[i]*i+phi[i-1])%P; return; } ll GetS(ll n) {return n*(n+1)/2%P;} ll GetSS(ll n) {return n*(n+1)%P*(2*n+1)%P*((P+1)/6)%P;} ll GetPhi(ll n){ if(n<N)return phi[n]; if(mp[n])return mp[n]; ll ans=GetSS(n); for(ll l=2,r;l<=n;l=r+1){ r=n/(n/l); (ans-=GetPhi(n/l)*(GetS(r)-GetS(l-1))%P)%=P; } mp[n]=ans; return ans; } ll solve(ll n){ ll ans=0; if(!n)return 0; for(ll l=1,r;l<=n;l=r+1){ r=n/(n/l); (ans+=(GetPhi(n/l)+1)*(r-l+1)%P)%=P; } return ans*((P+1)/2)%P; } signed main() { ll l,r,ans;Prime(); scanf("%lld%lld",&l,&r); ans=(solve(r)-solve(l-1))%P; printf("%lld\n",(ans+P)%P); return 0; }