题解2.9 最大公约数之和 UVa11426
例题2.9 最大公约数之和 UVa11426
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]); } }
版权声明:本文为博主原创文章,未经博主允许不得转载。