uva11426(欧拉函数)

来源:互联网 发布:淘宝上有天猫标志的 编辑:程序博客网 时间:2024/05/17 08:55

题意:求sum(gcd(i,j))(1<=i<j<=n,1<n<4000001)

题解:这题是欧拉函数的妙用。sum[n]=sum[n-1]+gcd(1,n)+gcd(2,n)+...+gcd(n-1,n)。设fgcd(x,n)=i。(1<=x<n)。两边同除以i这个gcd,就变成gcd(x/i,n/i)=1。那么求出cnt(x/i),再乘上i,就是对满足约数gcd(x,n)=i的gcd求和了。而cnt(x/i)就是euler(n/i)。所以先筛法打表欧拉函数,再求和即可。

代码:

#include<bits/stdc++.h>#define debug cout<<"aaa"<<endl#define mem(a,b) memset(a,b,sizeof(a))#define LL long long#define lson l,mid,root<<1#define rson mid+1,r,root<<1|1#define MIN_INT (-2147483647-1)#define MAX_INT 2147483647#define MAX_LL 9223372036854775807i64#define MIN_LL (-9223372036854775807i64-1)using namespace std;const int N = 4000000 + 5;const int mod = 1000000000 + 7;LL euler[N];LL s[N],f[N];int n; void Geteuler(){//筛法求欧拉函数 mem(euler,0);euler[1]=1;for(int i=2;i<N;i++){if(!euler[i]){for(int j=i;j<N;j+=i){if(!euler[j]) euler[j]=j;euler[j]=euler[j]/i*(i-1);}}}}int main(){Geteuler();mem(f,0),mem(s,0);for(int i=1;i<N;i++){for(int j=i+i;j<N;j+=i){f[j]+=i*euler[j/i];//求gcd(x,j)=i的gcd之和 }}for(int i=2;i<N;i++){s[i]=s[i-1]+f[i];}while(~scanf("%d",&n)&&n){printf("%lld\n",s[n]);}return 0;}