UVA 11426 - GCD - Extreme (II) (数论)

题目地址:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2421


题意简单。

题解:

设f(n)=gcd(1,n)+gcd(2,n)+……+gcd(n-1,n);s(n)=f(1)+f(2)+……f(n).所以有s(n)=s(n-1)+f(n).现在关键是求f(n)。

设g(n,i)表示所有满足gcd(x,n)=i的正整数x的个数i<n,那么f(n)=sum(i*g(n,i)),i的n的约数,gcd(x,n)=i -> gcd(x/i,n/i)=1,所以满足条件的x/i有phi(n/i)个。

但是如果依次计算f(n),需要枚举n的所以约数,如果吧思路逆过来,对每个i枚举他的倍数并更新f(n),时间复杂度就很小了。


AC代码:

#include <iostream>
#include <cstdio>
#include <cstring>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <list>
#include <deque>
#include <queue>
#include <iterator>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <cctype>
using namespace std;

typedef long long LL;
const int N=4000001;
const int mod=1000007;
const int INF=0x3f3f3f3f;
const double PI=acos(-1.0);

LL phi[N],xh[N];

void phi_table()
{
    int i,j;
    memset(phi,0,sizeof(phi));
    xh[1]=0;
    phi[1]=1;
    for(i=2;i<=N;i++)
    {
        if(!phi[i])
        {
            for(j=i;j<=N;j+=i)
            {
                if(!phi[j])
                    phi[j]=j;
                phi[j]=phi[j]/i*(i-1);
            }
        }
        for(j=i;j<=N;j+=i)
            xh[j]+=j/i*phi[i];
    }
    for(i=2;i<=N;i++)
        xh[i]+=xh[i-1];
}

int main()
{
    int n,i,j;
    phi_table();
    while(cin>>n&&n)
    {
        printf("%lld\n",xh[n]);
    }
    return 0;
}


你可能感兴趣的:(UVA 11426 - GCD - Extreme (II) (数论))