【P2303】Longge的问题

题目大意:求\[\sum\limits_{i=1}^ngcd(n,i)\]

题解:发现 gcd 中有很多是重复的,因此考虑枚举 gcd。
\[\sum\limits_{i=1}^ngcd(n,i)=\sum\limits_{d|n}d\sum_{i=1}^n[gcd(i,n)=d]=\sum\limits_{d|n}d\sum_{i=1}^{\lfloor n/d\rfloor}[gcd(i,{n\over d})=1]=\sum\limits_{d|n}d\phi(n/d)\]

代码如下

#include <bits/stdc++.h>
#define fi first
#define se second
#define pb push_back
#define mp make_pair
#define all(x) x.begin(),x.end()
#define cls(a,b) memset(a,b,sizeof(a))
#define debug(x) printf("x = %d\n",x)
using namespace std;
typedef long long ll;
typedef pair<int,int> P;
const int dx[]={0,1,0,-1};
const int dy[]={1,0,-1,0};
const int mod=1e9+7;
const int inf=0x3f3f3f3f;
//const int maxn=
const double eps=1e-6;
inline ll gcd(ll a,ll b){return b?gcd(b,a%b):a;}
inline ll sqr(ll x){return x*x;}
inline ll read(){
    ll x=0,f=1;char ch;
    do{ch=getchar();if(ch=='-')f=-1;}while(!isdigit(ch));
    do{x=x*10+ch-'0';ch=getchar();}while(isdigit(ch));
    return f*x;
}
/*--------------------------------------------------------*/

ll n;

inline ll phi(ll x){
    ll ret=x;
    for(int i=2;i<=sqrt(x);i++){
        if(x%i==0){
            ret=ret/i*(i-1);
            while(x%i==0)x/=i;
        }
    }
    if(x>1)ret=ret/x*(x-1);
    return ret;
} 
ll calc(ll x){
    ll ret=0;
    for(int i=1;i<=sqrt(x);i++){
        if(x%i==0){
            ret+=(ll)i*phi(x/i);
            if(i*i!=x)ret+=(ll)x/i*phi(i);
        }
    }
    return ret;
}

void read_and_parse(){
    n=read();
}

void solve(){
    printf("%lld\n",calc(n));
}

int main(){
    read_and_parse();
    solve();
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/wzj-xhjbk/p/10711122.html