算法提高 欧拉函数

题目链接

问题描述

  给定一个大于1,不超过2000000的正整数n,输出欧拉函数,phi(n)的值。
  如果你并不了解欧拉函数,那么请参阅提示。

提示

  欧拉函数phi(n)是数论中非常重要的一个函数,其表示1到n-1之间,与n互质的数的个数。显然的,我们可以通过定义直接计算phi(n)。
  当然,phi(n)还有这么一种计算方法。
  首先我们对n进行质因数分解,不妨设n=p1^a1 * p2^a2 * ... * pk^ak (这里a^b表示a的b次幂,p1到pk为k个互不相同的质数,a1到ak均为正整数),那么
  phi(n)=n(1-(1/p1))(1-(1/p2))....(1-(1/pk))
  稍稍化简一下就是
  phi(n)=n(p1-1)(p2-1)...(pk-1)/(p1*p2*...*pk)

计算的时候小心中间计算结果超过int类型上界,可通过调整公式各项的计算顺序避免(比如先做除法)!

欧拉函数具体解释:欧拉函数

 方法一:用试除法依次判断内的所有素数是否是n的因子。只需要每次找到一个素因子之后 把它“除干净”,即可保证找到的因子都是素数。

#include 
#include 
using namespace std;

int eulerPhi(int n) {
	int ans = n;
		for(int i = 2, m = sqrt(n+0.5); i <= m; i++) 
			if(n % i == 0) {
				ans = ans / i * (i-1);
				while(n % i == 0) n /= i;
			}
	if(n > 1) ans = ans / n * (n-1);
	return ans;
}

int main(int argc, char** argv) {
	int n;
	cin>> n;
	cout<< eulerPhi(n)<< endl;
	return 0;
}

方法二:1~n中所有数的欧拉phi函数值。并不需要依次计算。可以用与筛法求素数非常类似的方法,在O(nloglogn)时间内计算完毕 。

#include 
using namespace std; 
const int N = 2000000+5;
int phi[N]; 
void phiTable(int n, int* phi) {
	for(int i = 2; i <= n; i++) phi[i] = 0;
		phi[1] = 1;
		for(int i = 2; i <= n; i++) 
			if(!phi[i])
				for(int j = i; j <= n; j += i) {
					if(!phi[j]) phi[j] = j;
					phi[j] = phi[j] / i * (i-1);
			}
}
 
int main(int argc, char** argv) {
	int n;
	cin>> n;
	phiTable(n,phi);
	cout<< phi[n]<< endl;
	return 0;
}

 

输入格式

  在给定的输入文件中进行读入:
  一行一个正整数n。

输出格式

  将输出信息输出到指定的文件中:
  一行一个整数表示phi(n)。

样例输入

17

样例输出

16

你可能感兴趣的:(数论,算法竞赛入门经典(第二版))