Longge's problem
Time Limit: 1000MS | Memory Limit: 65536K | |
Total Submissions: 9190 | Accepted: 3073 |
Description
Longge is good at mathematics and he likes to think about hard mathematical problems which will be solved by some graceful algorithms. Now a problem comes: Given an integer N(1 < N < 2^31),you are to calculate ∑gcd(i, N) 1<=i <=N.
"Oh, I know, I know!" Longge shouts! But do you know? Please solve it.
"Oh, I know, I know!" Longge shouts! But do you know? Please solve it.
Input
Input contain several test case.
A number N per line.
A number N per line.
Output
For each N, output ,∑gcd(i, N) 1<=i <=N, a line
Sample Input
2 6
Sample Output
3 15
题意:给出一个数n,让你求1-n中所有的数与n的最大公约数的和。
思路:这题是欧拉函数的应用。假设x与n的最大公约数是a,也就是gcd(x,n)=a,那么我们就可以知道gcd(x/a,n/a)=1,也就是x/a与n/a互质。
这说明在1-n中与 n 的最大公约数为a的数都与n/a互质,所以我们就用欧拉函数求出1-n/a中,与n/a互质的数有多少个,其中,a是n的约数,所以遍历所有n的约数。
这题求的是与n的最大公约数的和sum,所以当a是n的约数时,sum就要加上a*欧拉(n/a);
代码:
1 #include<iostream> 2 #include<cstring> 3 #include<cstdio> 4 #include<string> 5 #include<cmath> 6 #include<algorithm> 7 #include<stack> 8 #include<queue> 9 #define eps 1e-7 10 #define ll long long 11 #define inf 0x3f3f3f3f 12 #define pi 3.141592653589793238462643383279 13 using namespace std; 14 ll euler(ll n) // 求欧拉函数值 15 { 16 ll res = n,a = n; 17 for(ll i=2; i*i<=a; ++i) 18 { 19 if(a%i==0) 20 { 21 res = res/i*(i-1); 22 while(a%i==0) a /= i; 23 } 24 } 25 if(a > 1) res = res/a*(a-1); 26 return res; 27 } 28 29 int main() 30 { 31 ll n; 32 while(scanf("%lld",&n)!=EOF) 33 { 34 ll ans=0; 35 for(ll i=1; i*i<=n; ++i) //遍历求n的约数 36 { 37 if(n%i == 0) 38 { 39 ans += i*euler(n/i); //euler(n/i)求出与 n 的最大公约数为 i 的数有多少,再乘上公约数 i 40 if(n/i != i) 41 ans += euler(i)*(n/i); //同理求出与n的最大公约数为n/i的数有多少 42 } 43 } 44 printf("%lld ",ans); 45 } 46 return 0; 47 }