题意
求 ∑i=1ngcd(i,n) ∑ i = 1 n g c d ( i , n )
题解
这题…真的要写一下了…
其实吧,结果就是
∑i|ni∗φ(ni)
∑
i
|
n
i
∗
φ
(
n
i
)
然后!怎么求
varphi
v
a
r
p
h
i
这里给出一个超级厉害的做法!线筛+杜教筛!
当然如果你信了的话呢,咱们握握手吧!
直接求复杂度就是 n−−√ n 呀..很..赞..的!
代码
//正解!
#include <cstdio>
#include <cmath>
#define ll long long
ll n,ans;
ll phi(ll x){
ll t=x;
for(ll i=2;i<=sqrt(n);i++){
if(x%i==0){
t=t/i*(i-1);
while(x%i==0) x/=i;
}
}
if(x>1) t=t/x*(x-1);
return t;
}
int main(){
// freopen("a.in","r",stdin);
scanf("%lld",&n);
for(int i=1;i<=sqrt(n);i++){
if(n%i==0){
ans+=(ll)i*phi(n/i);
ll x=n/i;
if(i!=x) ans+=(ll)x*phi(n/x);
}
}
printf("%lld\n",ans);
return 0;
}
//傻子版!
#include <cstdio>
#include <cstring>
#include <cmath>
#include <map>
#include <algorithm>
using namespace std;
#define ll long long
#define N 2000010
#define U unsigned int
ll ans=0,phi[N],s1[N];
int n,tot,notprime[N],prime[N];
inline void euler(){
phi[1]=1;
for(int i=2;i<=2000000;i++){
if(!notprime[i]) prime[++tot]=i,phi[i]=i-1;;
for(int j=1;j<=tot && prime[j]*i<=2000000;j++){
notprime[prime[j]*i]=1;
if(i%prime[j]==0){
phi[prime[j]*i]=phi[i]*prime[j];
break;
}phi[prime[j]*i]=phi[i]*phi[prime[j]];
}
}
for(int i=2;i<=2000000;i++) phi[i]+=phi[i-1];
}
map<int,ll>mp;
inline ll calc(int x){
if(x<=2000000) return phi[x];
if(mp[x]) return mp[x];
ll res=(ll)x*(x+1)>>1;
for(U i=2,last;i<=x;i=last+1){
last=x/(x/i);
res-=calc(x/i)*(last-i+1);
}mp[x]=res;
return res;
}
int main(){
freopen("a.in","r",stdin);
freopen("a.out","w",stdout);
scanf("%d",&n);
euler();memset(s1,0,sizeof(s1));
for(int i=1;i<=sqrt(n);i++){
if(n%i==0) ans+=(calc(n/i)-calc(n/i-1))*i;
int x=n/i;
if(n%x==0 && x!=i) ans+=(calc(n/x)-calc(n/x-1))*x;
}
printf("%lld",ans);
return 0;
}