例题2.9 最大公约数之和 UVa11426

来源:互联网 发布:查看数据库的存储过程 编辑:程序博客网 时间:2024/06/04 00:49

1.题目描述:点击打开链接

2.解题思路:本题利用线性筛+打表解决。设f(n)=gcd(1,n)+gcd(2,n)+...+gcd(n-1,n).那么最终的答案就是S(n)=f(2)+f(3)+...+f(n)。因此,只需要快速计算f(n),即可递推得到所有答案。注意到gcd(x,n)是n的约数,我们不妨利用约数来分类计数。令g(n,i)表示gcd(x,n)=i且x<n的数的个数。那么f(n)=sum{i*g(n,i)|i是n的约数}。又注意到gcd(x,n)=i的个数和gcd(x/i,n/i)=1的个数一样,即phi(n/i)个,因此,f(n)=sum{i*phi(n/i)|i是n的约数}。此处我们可以利用线性筛素数的思想,枚举i的倍数j,然后更新所有的f[j]即可。

3.代码:

//#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<algorithm>#include<cassert>#include<string>#include<sstream>#include<set>#include<bitset>#include<vector>#include<stack>#include<map>#include<queue>#include<deque>#include<cstdlib>#include<cstdio>#include<cstring>#include<cmath>#include<ctime>#include<cctype>#include<functional>using namespace std;#define me(s)  memset(s,0,sizeof(s))#define rep(i,n) for(int i=0;i<(n);i++)typedef long long ll;typedef unsigned int uint;typedef unsigned long long ull;typedef pair <int, int> P;const int N=4000000+10;int phi[N];void phi_table(int n){    for(int i=2;i<n;i++)phi[i]=0;    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 S[N+1],f[N+1];int main(){    phi_table(N);      memset(f,0,sizeof(f));    for(int i=1;i<N;i++)        for(int n=i*2;n<N;n+=i) //利用线性筛法,计算f[n]        f[n]+=i*phi[n/i];    S[2]=f[2];    for(int n=3;n<N;n++)        S[n]=S[n-1]+f[n];//递推得到S[n]    int n;    while(~scanf("%d",&n)&&n)    {        printf("%lld\n",S[n]);    }}

0 0
原创粉丝点击