忽然想寫一篇有關歐拉函數的博客

關於歐拉函數:ios

定義:svg

φ(n)表示1~n中與n互質的數的個數;函數

求法:spa

已知n的標準分解式爲:code

(哦對了,這裏全部的因子都是質因子)blog

​那麼
ci

而後求歐拉函數的兩種方法:it

1.按照定義暴力求解:io

int phi(int n){
    int ret=n;
    for(int i=2;i*i<=n;i++){
        if(n%i==0){
            ret-=ret/i;
            while(n%i==0) n/=i;
        }
    }
    if(n>1) ret-=ret/n;
    return ret;
}

解釋一下:class

對於歐拉函數φ來講,咱們每*(1-1/pn),就至關於在原數的基礎上減掉原數*1/pn(這裏的原數並非指n,而是指n*某些數以後的數),假設原數爲ret,那麼咱們將ret*(1-1/pz)的值就至關於ret-ret*1/pz,由此咱們得出了ret-=ret/i;而後將n中的全部i通通除掉,防止出現再算一次的可涼(就是很涼)狀況。最後,若是n>1,說明咱們還有一個因子沒有枚舉到,此時n就是當前因子,用上方式子再減一下就行了;

2.歐拉篩時順帶着求出來了???

而後歐拉篩的話,能夠求到的值比較小,若是單純求φ的話,不如用定義呢

#include<iostream>
#include<cstdlib>
#include<algorithm>
#include<ctime>

using namespace std;

int n,cnt,maxx;
int prime[10000010],phi[10000010];
bool not_[10000010];

void shai(){
    for(int i=2;i*i<=100000000;i++){
        if(!not_[i]) {
            prime[++cnt]=i;
            phi[i]=i-1;
        }
        for(int j=1;j<=cnt&&i*prime[j]<=n;j++){
            not_[i*prime[j]]=1;
            if(i%prime[j]==0) {
                phi[i*prime[j]]=phi[i]*prime[j];
                break;
            }
            else phi[i*prime[j]]=phi[i]*phi[prime[j]];
        }
    }
}

int main(){
    freopen("data.in","r",stdin);
    freopen("data.ans","w",stdout);
    cin>>n;
    shai();
    printf("%d",phi[n]);
}

end-

相關文章
相關標籤/搜索