题目链接:http://acm.nyist.net/JudgeOnline/problem.php?pid=333
解题思路:
欧拉函数应用,但是这个题和上个不一样,不能打表算,因为n的范围为整形,数组无法存下,所以只能用最原始的素分解来写。。。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
const int N = 65540;
int prim[N];
void Fast_Prim() //素数打表
{
int limit = sqrt(N * 1.0);
int num = 0;
memset(prim, 0, sizeof(prim));
for(int i = 2; i < limit; ++i)
if(!prim[i])
for(int j = i * i; j < N; j += i)
prim[j] = true;
for(int i = 2; i < N; ++i)
if(!prim[i])
prim[num++] = i;
}
int Prim_Induce(int n) //素分解
{
int num, sum = n;
for(int i = 0; prim[i] * prim[i] <= n; ++i)
{
if(n % prim[i] == 0)
{
sum = sum / prim[i] * (prim[i] - 1);
while(n % prim[i] == 0)
n /= prim[i];
}
}
if(n != 1)
sum = sum / n * (n - 1);
return sum;
}
int main()
{
Fast_Prim();
int n;
while(~scanf("%d", &n))
printf("%d\n", Prim_Induce(n));
return 0;
}
优化做法:
不需要素分解,在找素数的过程就计算欧拉函数的值。
代码如下:
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
int Euler(int n)
{
int res = n;
for(int i = 2; i * i <= n; ++i)
{
if(n % i == 0)
{
res = res / i * (i - 1);
while(n % i == 0)
n /= i;
}
}
if(n != 1)
res = res / n * (n - 1);
return res;
}
int main()
{
int n;
while(~scanf("%d", &n))
printf("%d\n", Euler(n));
return 0;
}