【BZOJ2705】【Sdoi2012】Longge的问题

Description

Longge的数学成绩非常好，并且他非常乐于挑战高难度的数学问题。现在问题来了：给定一个整数N，你需要求出$\Sigma gcd(i, N) (1 \leq i \leq N)$

6

15

Solution

$f(k)$表示$gcd(m,n)=k$$m(m \leq n)$的个数，因此$gcd(m/k,n/k)=1$,于是有$f(k)=\varphi (n/k)$.

Code

#include <stdio.h>
#include <math.h>
#define MN (1<<16)
#define R register
#define ll long long
#define file(x) freopen(#x".in","r",stdin);freopen(#x".out","w",stdout);
#define end fclose(stdin);fclose(stdout)
ll n,ans;int phi[MN+5],pr[MN],pn,m;bool b[MN+5];
void pre(){
phi[1]=1;for (R int i=2; i<=m; ++i){
if (!b[i]){
pr[++pn]=i;
phi[i]=i-1;
}
for (R int j=1; j<=pn; ++j){
if (1ll*i*pr[j]>m) break;
b[i*pr[j]]=1;
if (i%pr[j]==0){
phi[i*pr[j]]=phi[i]*pr[j];
break;
}phi[i*pr[j]]=phi[i]*(pr[j]-1);
}
}
}
inline ll getphi(ll x){
R ll q=x,res=x;
for (R int i=1; i<=pn; ++i)
if (!(q%pr[i])){
res=res/pr[i]*phi[pr[i]];
while((!(q%pr[i]))) q/=pr[i];
}
if (q>1) res=res/q*(q-1);return res;
}
int main(){
scanf("%lld",&n);m=floor(sqrt(n));pre();
for (R int t=1; t<=m; ++t)
if (n%t==0){
ans+=t*getphi(n/t);
if (t*t<n) ans+=n/t*phi[t];
}printf("%lld\n",ans);
return 0;
}

posted @ 2017-11-02 10:17  Melacau  阅读(121)  评论(0编辑  收藏  举报