[數論]小於n且與n互素的個數(歐拉函數)

/*
Name:小於n且與n互素的個數(歐拉函數)

Actor:HT

Time:2015年8月10日

Error Reporte:

*/
#include <iostream>
#include <stdio.h>
#include <conio.h>
#include <string.h>

using namespace std;

//歐拉函數:
//f(n) = n*TT[ 1/p * (p-1) ]
//其中 p 是 n 的質因數
//實現:對於每一個質因數,除p乘p-1

int euler(int n)
{
	int p;
	int m = sqrt(n + 0.5);	//m用來界定質因子的範圍
	int ans = n;
	for (p = 2; p <= m; p++)
	{
		if (n%p == 0)
		{
			ans = ans / p * (p - 1);
			while (n%p == 0) n /= p;	//源於唯一分解定理,排除非素
		}
	}
	if (n != 1) ans = ans / n*(n - 1);	//如果本身也是素數,就要除一下
	return ans;
}

//篩選法求歐拉函數  O(nloglogn)
int table[10000];
void euler_table(int n)
{
	int i, j;
	for (i = 1; i <= n; i++)
		table[i] = i;
	for (i = 2; i <= n; i++)
	{
		if (table[i] == i)
		{
			for (j = i; j <= n; j += i)
			{
				table[j] = table[j]/i*(i - 1);
			}
		}
	}
}


int main()
{
	int n; 
	euler_table(100);
L:	scanf("%d", &n);
	printf("%d     ", table[n]);
	n = euler(n);
	printf("%d\n", n);
	goto L;
}

//歐拉函數的推導:

//歐拉函數 f(n) = 小於n的與n互素的數的個數(注意不是素因數)
//“積性函數” F(X*Y),當且僅當 GCD(X,Y)= 1 時, F(X*Y) = F(X)* F(Y)
//歐拉函數是積性函數(我也不知道爲什麼)
//所以  根據唯一分解定理   n = p1^a1 * p2^a2 * ... * pn^an
//f(n) = p(p1^a1) * p(p2^a2) * ... * p(pn^an)
//對於p1^a1 其中因數的個數爲 p1^a1 - p1^a1/p1 == p1^a1 * (1 - 1/p1)
//f(n) = p1^a1*p2^a2... ... *(1 - 1/p1)*(1 - 1/p2)*... ...
//     = n * TT(1 - 1/pi) = n * TT[1/pi*(pi-1)] 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章