一文读懂欧拉函数
歐拉函數φ(N)表示小于或等于N的正整數中與N互質的數的個數。又稱φ函數、歐拉商數。
下面介紹歐拉函數的幾個性質:
我們根據這幾個性質就可以求出歐拉函數。
基本思路是首先置φ(N)=N,然后再枚舉素數p,將p的整數倍的歐拉函數φ(kp)進行如下操作。
代碼如下:
#include
using?namespace?std;
const?int?MAX?=?1024;
int?N;
int?p[MAX],?phi[MAX];
int?main()
{
????cin?>>?N;
????for(int?i?=?1;?i?<=?N;?i++) // 初始化
????{?p[i]?=?1;?phi[i]?=?i;?}
????p[1]?=?0; // 1不是素數
????for(int?i?=?2;?i?<=?N;?i++) // 篩素數
????{
????????if(p[i])
????????{
????????????for(int?j?=?i?*?i;?j?<=?N;?j?+=?i)
????????????{?p[j]?=?0;?}
????????}
????}
????for(int?i?=?2;?i?<=?N;?i++) // 求歐拉函數
????{
????????if(p[i])
????????{
????????????for(int?j?=?i;?j?<=?N;?j?+=?i) // 處理素因子p[i]
????????????{
????????????????phi[j]?=?phi[j]?/?i?*?(i?-?1); // 先除后乘,防止中間過程超出范圍
????????????}
????????}
????}
????cout?<<?"Primes: "?<<?endl;
????for(int?i?=?1;?i?<=?N;?i++)
????{?if(p[i])?{?cout?<<?i?<<?" ";?}?}
????cout?<<?endl;
????cout?<<?"Euler Phi Function: "?<<?endl;
????for(int?i?=?1;?i?<=?N;?i++)
????{?cout?<<?phi[i]?<<?" ";?}
????return?0;
}
以上是關于歐拉函數的求法,對于它的應用,這里暫且介紹一個——求解原根的個數。
對于原根的定義,我們可以這樣來敘述:
若存在一個實數a,使得( a^i ) mod N,a∈{1,2,3,?,N}的結果各不相同,我們就成實數a為N的一個原根。
原根的個數等于φ(φ(N))。這樣我們就可以很方便的求出原根的個數。
代碼如下:
#include
#include
using?namespace?std;
typedef?unsigned?long?long?ull;
ull?N;
ull phi(ull?x);
int?main()
{
????cin?>>?N;
????cout?<<?phi(phi(N))?<<?endl;
????return?0;
}
ull phi(ull?x)
{
????ull?ans?=?x;
????ull?m?=?(ull)sqrt(x);
????for(ull?i?=?2;?i?<<=?m;?i++)
????{
????????if(x?%?i?==?0) // 求素因子
????????{
????????????ans?=?ans?/?i?*?(i?-?1); // 運用通項求解歐拉函數
????????????while(x?%?i?==?0) // 每個素因子只計算一次
????????????{?x?/=?i;?}
????????}
????}
????if(x?>?1) // 防質數
????{?ans?=?ans?/?x?*?(x?-?1);?}
????return?ans;
}
轉自:ivy-end
http://www.ivy-end.com/archives/1021
總結
- 上一篇: 魔性十足的数学动态图,这种东西都拿出来分
- 下一篇: 一文读懂 AVL 树