歐拉函數

歐拉函數Euler(x)html

Euler(n)表示1-n之間與n互質的個數,例如Euler(4) = 2,其中1和3與4互質。(數論裏面規定Euler(1) = 1,而且1與任何數互質)。算法

歐拉函數的通項表達式爲:函數

還有其一些推論:學習

當n >= 1時,1 - n中與n互質的整數和爲nEuler(n)/2;spa

那歐拉函數怎麼求呢?3d

首先咱們再來學習下一個概念:積性函數。htm

函數f(x)對於任意正整數a, b,若是a,b互質而且知足f(ab) = f(a)f(b),則f(x)爲積性函數。其中若a,b不互質仍知足f(ab) = f(a)f(b)則稱f(x)爲徹底積性函數。blog

對於一個數n和他的約數p:ci

對於任意一個正整數n, 均有:get

再根據積性函數的性質得:

也就是先預處理使Euler[i] = i,再去考慮能被n的質因數,只要把其中一個質因數p改爲p - 1便可。

附上僞代碼:

const int N = 1000000 + 5;

int euler[N];

void euler_function(){
    for(int i = 0; i <= N - 5; i ++) euler[i] = i;
    for(int i = 2; i <= N - 5; i ++)
        if(euler[i] == i)
            for(int j = 1; i * j <= N - 5; j ++) 
                euler[i * j] = euler[i * j] / i * (i - 1);
}

 固然,上述算法(相似於埃式篩法)的複雜度爲(n + nloglogn)。

而後咱們再想一想篩選素數的方法除了埃式篩法,還有更快速的線篩(素數篩選傳送門

附上代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
const int N = 1000000 + 5;

int n;

int check[N], euler[N], prime[N];

void euler_function(){
    memset(check, 0, sizeof(check));
    euler[1] = 1;
    int tot = 0;
   for(int i = 2; i <= N - 5; i ++){
        if(!check[i]){
            prime[tot ++] = i;
            euler[i] = i - 1;
        }
        for(int j = 0; j < tot; j ++){
            if(i * prime[j] > N - 5) break;
            check[i * prime[j]] = 1;
            if(i % prime[j] == 0){
                euler[i * prime[j]] = euler[i] * prime[j];
                break;
            }
            else euler[i * prime[j]] = euler[i] * (prime[j] - 1);
        }
    }
}

int main(){
    euler_function();
    while(scanf("%d", &n) == 1)printf("%d\n", euler[n]);
    return 0;
}

  

 參考論文 :http://www.docin.com/p-687551303.html

相關文章
相關標籤/搜索