√n求單值歐拉函數


基本定理:

 

 

首先看一下核心代碼:

核心代碼

 

 

原理解析:

當初我看不懂這段代碼,主要有這么幾個問題:

1.定理里面不是一開始寫了一個n*xxx么?為什么代碼里沒有*n?

2.ans不是*(prime[i]-1)么?為什么到了第二個while循環變成*prime[i]了?

3.定理里面不是要/pi么?為什么代碼里沒有/pi?????????????

 

公式化簡

首先我們來分析一下整個程序的原理,如果把程序的原理搞明白了,這三個問題也就自然而然的解決了

這個程序的原理是基於唯一分解定理:

 

 那么我們可以把n拆開,再帶回到歐拉函數公式中,然后再約分一下:

LaTex代碼:

1 ans=p_1^a^1*p_2^a^2*.......*p_i^a^i*\frac{p_1-1}{p_1}*\frac{p_2-1}{p_2}*....*\frac{p_i-1}{p_i}
2    \newline 
3    =p_1^a^1*\frac{p_1-1}{p_1}*.......*p_2^a^2*\frac{p_2-1}{p_2}*....p_i^a^i*\frac{p_i-1}{p_i}
4    \newline 
5    =p_1^a^{1-1}*({p_1-1})*.......*p_2^a^{2-1}*({p_2-1})*....p_i^a^{i-1}*({p_i-1})

 

解答問題

首先這里的代碼實現還有一個小技巧:
我們在while之前把x/prime[i],這就相當於讓ans少*一個prime[i],這樣就可以解決求指數ai-1的問題了

 

現在再回去看一下剛開始的三個問題,仔細想一想

 

提示:

下面有答案,

但請認真思考以后再看,

 

 

 

 

 

 

 

 

 

 

 

答案在下面:

 

 

 

 

 

 

 

 

 

 

 

 

 

1.定理里面不是一開始寫了一個n*xxx么?為什么代碼里沒有*n?

因為n被唯一分解了,while循環里面的內容就是用來*n的

2.ans不是*(prime[i]-1)么?為什么到了第二個while循環變成*prime[i]了?

*prime是為了讓答案最終*n

3.定理里面不是要/pi么?為什么代碼里沒有/pi?????????????

被化簡了,不明白的可以看上面的化簡過程

 

 

完整代碼

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 using namespace std;
 6 const int MAXN=1000001;
 7 int prime[MAXN];
 8 int mu[MAXN]= {0,1};
 9 int n;
10 int tot=0;
11 int vis[MAXN]= {1,1};
12 void read(int &n) {
13     char c='+';
14     int x=0;
15     bool flag=0;
16     while(c<'0'||c>'9') {
17         c=getchar();
18         if(c=='-')flag=1;
19     }
20     while(c>='0'&&c<='9') {
21         x=x*10+c-48;
22         c=getchar();
23     }
24     flag==1?n=-x:n=x;
25 }
26 void ou() {
27     for(int i=2; i<=n; i++) {
28         if(!vis[i])
29             prime[++tot]=i,mu[i]=-1;
30         for(int j=1; j<=tot&&j*prime[i]<=n; j++) {
31             vis[i*prime[j]]=1;
32             if((i%prime[j])==0) {
33                 mu[i*prime[j]]=0;
34                 break;
35             }
36             mu[i*prime[j]]=-mu[i];
37         }
38     }
39 }
40 int getphi(int x) {
41     int ans=1;
42     for(int i=1; i<=tot&&prime[i]*prime[i]<=x; i++) 
43     {
44         if(x%prime[i]==0) 
45         {
46             ans*=(prime[i]-1);
47             x=x/prime[i];
48             while(x%prime[i]==0) 
49             {
50             ans*=prime[i];
51             x/=prime[i];
52             }
53         }
54         
55     }
56     if(x>1)
57         ans*=x-1;
58     return ans;
59 }
60 int main() {
61     n=1001;
62     ou();
63     int c;
64     printf("please input the num\n");
65     while(cin>>c)
66         printf("the num`s phi is %d\n",getphi(c));
67     return 0;
68 
69 }

 

里面還亂入了線性求莫比烏斯函數的方法,,

懶得刪了,,,

 

結尾啰嗦幾句

求單值歐拉函數就講到這里,

其實對於這份代碼還有一種很玄學的理解方法,

但是我的這種方法比較簡單易懂,

而且這兩種理解方法從本質上來說是一樣的

這里不在贅述

 

最后再說一下,這里只介紹了求單值歐拉函數的方法,

實際上歐拉函數還有線性篩法(因為歐拉函數是積性函數)

有空再介紹吧

 

另外,因為本人是第一次接觸歐拉函數,所以本文肯定有成堆的bug,如果您找出了bug,可以在評論區留言或者通過其他方式聯系本人

 

謝謝!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM