题目描述
f(n) = GCD(1, n) + GCD(2, n) + GCD(3, n) + ~ ~ ~ + GCD(n - 1, n).
输入
每行一个整数N (1 < N < 4000000),输入0的时候终止.
输出
对于输入的每一行输出要求的和.
样例输入
3176 17681 13080 0
样例输出
12684 17680 182220
我们假设gcd(n,i) = k,则gcd(n/k,i/k) = 1。即假设gcd(n/k, x ) = 1,则gcd(n,x*k) = k。gcd(n,i) = k,k的取值是确定的,即n的所有因子,所以,满足gcd(n/k,x) = 1个x的个数乘以k即为所有满足gcd(n,i) = k 的和。因此就转化为n/k的欧拉函数的值乘以k的所有的和。
举个例子12来说,12的因子为1,2,3,4,6,12,则和为12/1的欧拉函数值*1 + 12/2的欧拉函数值 * 2 + 12/3的欧拉函数值 * 3 + 12/4的欧拉函数值 * 4 + 12/6的欧拉函数值*6 + 12/12 的欧拉函数值 * 12。
我写的代码超时了... 无奈。
#include<cstdio> #include<cmath> int eular(int n) { int ret=1,i; for(i=2;i*i<=n;i++){ if(n%i==0){ n/=i,ret*=i-1; while(n%i==0) n/=i,ret*=i; } } if(n>1) ret*=n-1; return ret; } long long a[200000]; int main() { int n; while(scanf("%d", &n) && n){ long long sum = 0, l = 0; //int p = sqrt(n * 1.0); for(int i = 1; i <= n; i++){ if(n % i == 0){ a[++l] = i; } } for(int i = 1; i < l; i++){ long long m = n / a[i]; sum += eular(m) * a[i]; } printf("%lld\n", sum); } return 0; }
这是学长的代码, 表示看不懂。。。
#include<stdio.h> #include<string.h> #define A 4000001 int p[A],ans[A]; int main() { int N,i,j; memset(p,0,sizeof(p)); memset(ans,0,sizeof(ans)); p[1]=1; for(i=2;i<A;i++) //p[n]表示[1~n]与n互质的个数 if(!p[i]) for(j=i;j<A;j+=i) { if(!p[j]) p[j]=j; p[j]=p[j]/i*(i-1); } for(i=1;i<A;i++) //求结果 for(j=i+i;j<A;j+=i) ans[j]+=i*p[j/i]; while(scanf("%d",&N),N) printf("%d\n",ans[N]); }