USACO GCD Extreme(II)

Candy?發表於2016-08-21

題目大意:求gcd(1,2)+gcd(1,3)+gcd(2,3)+...+gcd(n-1,n)

-----------------------------------------------------------------

設f(i)=gcd(1,n)+...+gcd(n-1,n),則答案S(n)=f(2)+...+f(n)

如何求f

設g(n,i)表示滿足gcd(x,n)=1且x<n的x個數,則f(n)=sum{i*g(n,i):i|n}

gcd(x,n)=i的充要條件是x/i和n/i互質,所以gcd(n,i)=phi(n/i)

計算一片f用類似篩法的方法

------------------------------------

 

LuoguP2398題目描述

 

for i=1 to n 

 

for j=1 to n

 

 sum+=gcd(i,j)

 

給出n求sum. gcd(x,y)表示x,y的最大公約數.

----------------------------------------

很類似,在加上一個nf=gcd(1,n)+...+gcd(n,n)  f和nf加起來就行了

 

#include <iostream>
#include <cstdio>
#include <cstring>
using namespace std;
typedef long long ll;
const int N=1e5+5;
ll n,ans=0;

int phi[N];
void phiTable(int n){
    phi[1]=1;
    for(int i=2;i<=n;i++) if(!phi[i])
        for(int j=i;j<=n;j+=i){
            if(!phi[j]) phi[j]=j;
            phi[j]=phi[j]/i*(i-1);
        }
}

ll f[N],nf[N];
int main(int argc, const char * argv[]) {
    cin>>n;
    phiTable(n);
    
    for(int i=1;i<=n;i++)
        for(int j=i;j<=n;j+=i){
            nf[j]+=i*phi[j/i];
            if(j!=i) f[j]+=i*phi[j/i];
        }
    for(int i=1;i<=n;i++) ans+=f[i]+nf[i];
    cout<<ans;
    
    return 0;
}