USACO GCD Extreme(II)

题目大意:求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;
}

 

posted @ 2016-08-21 23:03  Candy?  阅读(273)  评论(0编辑  收藏  举报