http://poj.org/problem?id=2407
给出 n ,求欧拉函数 ϕ(n)
有两种做法:
1、 O(n) 线性筛法,适合 n 很小但是求欧拉函数次数很多的地方。由于此题 n 过大因此会TLE。
2、根据欧拉函数公式分解 n 的质因数,适合 n 比较大但是求欧拉次数很少的地方,适合本题。
1、 O(n) 线性筛
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 1000
using namespace std;
bool isPrime[MAXN];
int fai[MAXN]; //欧拉函数
int prime[MAXN],tot=0; //质数
void GetEular()
{
memset(isPrime,true,sizeof(isPrime));
fai[1]=1;
tot=0;
for(int i=2;i<MAXN;i++)
{
if(isPrime[i])
{
prime[++tot]=i;
fai[i]=i-1;
}
for(int j=1;j<=tot;j++)
{
if(i*prime[j]>MAXN) break;
isPrime[i*prime[j]]=false;
if(i%prime[j]==0)
{
fai[i*prime[j]]=fai[i]*prime[j];
break;
}
else
fai[i*prime[j]]=fai[i]*(prime[j]-1);
}
}
}
int main()
{
GetEular();
int n;
while(scanf("%d",&n)!=EOF&&n)
{
printf("%d\n",fai[n]);
}
return 0;
}
2、分解 n 的质因数
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <algorithm>
#define MAXN 1000
using namespace std;
int fai(int n)
{
int ans=n;
for(int i=2;i<=n;i++)
{
if(n%i==0)
{
ans=ans/i*(i-1);
while(n%i==0) n/=i;
}
}
return ans;
}
int main()
{
int n;
while(scanf("%d",&n)!=EOF&&n)
{
printf("%d\n",fai(n));
}
return 0;
}