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

来源:互联网 发布:阿里云企业邮箱地址 编辑:程序博客网 时间:2024/04/30 15:10

题目地址: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;}


原创粉丝点击