欧拉函数的基本性质详解(见该链接):https://blog.csdn.net/w144215160044/article/details/51158735
最大公约数和
发布时间: 2018年3月27日 09:20 时间限制: 1000ms 内存限制: 128M
已知n(1≤n≤2000000000),令g(n)=gcd(1,n)+gcd(2,n)+…+gcd(n,n),输出g(n)的值。gcd(a,b)表示a与b的最大公约数。
输入包含若干个数据,每行一个数n。
数据组数不超过50000 。
对于每个输入的n,在一行内输出g(n)。
2
6
3
15
请使用scanf和printf输入与输出。
数据比较多,容易超时!
#include<algorithm> //此代码暂时还不是很理解,先记录着吧 #include<cstdio> #include<string> #include<cstring> #include<cmath> #include<iostream> #define M 44721 #define N 1000010 using namespace std; int pNum, prime[M]; bool f[M]; int num = 101; void fun()//用素数筛选法建立素数表,从1到44721,因为n最大20 0000 0000,到根号n即可 { int i, j; pNum = 0; memset(f, true, sizeof(f)); f[0] = f[1] = false; for (i = 2; i <= (int)sqrt(M); i++) { if (f[i]) { for (j = i * i; j<M; j += i) f[j] = false; } } for (i = 2; i<M; i++) if (f[i]) prime[pNum++] = i; //先打表,将1-2000000000之间的素数全部找出来 } long long pow1(int a, int b)//求a^b,因为数据比较大,用pow函数可以会有精度问题 { int i; long long s; for (i = 0, s = 1; i<b; i++) s *= a; return s; } long long fun1(int a) { int i, s_a, s_b, cnt; cnt = -1; for (i = 0; prime[i] <= (int)sqrt(a); i++) { if (a%prime[i] == 0) { a /= prime[i]; cnt = prime[i]; s_a = prime[i]; s_b = 1; while (a%prime[i] == 0) { cnt *= prime[i]; a /= prime[i]; s_b++; } break; } } if (cnt == -1)//第二种情况 return (long long)a * 2 - 1;//注意int64的强制转换 if (a == 1)//第三种情况 return pow1(s_a, s_b - 1)*(s_b*(s_a - 1) + s_a); //第一种情况 return fun1(cnt)*fun1(a); } int main() { int n; fun(); while (scanf("%d", &n) != EOF) printf("%lld\n", fun1(n)); return 0; }
2018-04-05