日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Euler:欧拉函数&素数筛

發布時間:2023/12/10 编程问答 44 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Euler:欧拉函数&素数筛 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

一、歐拉函數

歐拉函數是小于x的整數中與x互質的數的個數,一般用φ(x)表示。

通式: ? 其中p1, p2……pn為x的所有質因數,x是不為0的整數。
  • 比如x=12,拆成質因數為12=2*2*3,
  • 12以內有1/2的數是2的倍數,那么有1-1/2的數不是2的倍數(1,3,5,7,9,11),
  • 這6個數里又有1/3的數是3的倍數,
  • 只剩下(1 - 1/2 - 1/3)的數既不是2的倍數,也不是3的倍數(1,5,7,11)。
  • 這樣剩下的12*(1 -?1/2?-?1/3)=4,即4個數與12互質,所以φ(12)=4。

證明:對于正整數x,

  • 如果x=1,則 φ(1) = 1。
    • 1與任何數(包括自身)都構成互質關系。
  • 如果x是質數,則 φ(x)=x-1 。
    • 質數與小于它的每一個數,都構成互質關系。比如5與1、2、3、4都構成互質關系。
  • 如果n只有一個質因數p,即x = p^k(p為質數,k>=1),則φ(pk)=pk(1-1/p)=pk-pk-1?。
    • 從1~x中,p的倍數共有x/p個,共占了1/p,則減去這些數后,還剩下x*(1-1/p)個。
    • 可以看出,上一種情況是 k=1 時的特例。
  • 如果n可以分解成兩個互質的整數之積,即n = p1 * p2,φ(x) = φ(p1?* p2) = φ(p1) * φ(p2)。
    • φ(a)=m,φ(b)=n,φ(a*b) = a(1-p1)(1-p2)...*b(1-q1)(1-q2)... = m*n
    • 歐拉函數是積性函數(若當m與n互質時,f(m?n)=f(m)?f(n) f(m*n)=f(m)*f(n)f(m?n)=f(m)?f(n),那么f是積性函數。)
  • 任意一個大于1的正整數,都可以寫成一系列質數的積。
  • 可以得到,φ(x) =?φ(p1)*φ(p2)*...*φ(pn) = x(1-1/p1)*(1-1/p2)*...*(1-1/pn).

一些(目前不需要的)性質:

  • 當n>2時,φ(n)是偶數。
  • 小于n的數中,與n互質的數的總和為:φ(n) * n / 2 (n>1)。
  • n的因數(包括1和它自己)的歐拉函數之和等于n。
  • 若n為奇數時,φ(2n)=φ(n)。
  • 對于任何兩個互質的正整數a,n(n>2)有:aφ(n)1(mod?n)此公式即?歐拉定理。
  • 當n=p 且 a與素數p互質(即:gcd(a,p)=1)則上式有: an-11(mod?n)公式即?費馬小定理。


求歐拉函數:

1.埃拉托斯特尼篩

求1~n所有數的歐拉函數:每次找到一個質數,就把它的倍數更新掉。復雜度大概是O(nlognlogn)。

void euler(int n) {for (int i=1; i<=n; i++) phi[i]=i;for (int i=2; i<=n; i++)if (phi[i]==i)//i是質數for(int j=i; j<=n; j+=i)phi[j]=phi[j]/i*(i-1); }

?

2.歐拉篩

求n的歐拉函數:每次找到一個最小的因數(一定為質因數),求出x*(1 - 1/p)。復雜度為O(n)。

?

int euler(int n) {int res=n,a=n;for(int i=2; i*i<=a; i++) {if(a%i==0) {res=res/i*(i-1);while(a%i==0) a/=i;}}if(a>1) res=res/a*(a-1); //有質數剩余 return res; }

?

對于x =?p1k1 * p2k2...,只需要求一次(1-p1)(1-p2)...就可以了,

為了保證每個質因數只被使用一次,通過以上的while循環把x中的p1除盡。

?

二、素數篩法

這里直接上歐拉算法了。關于埃氏和其他算法

int Prime(int N) {for(i=2; i<=N; i++) {if(!check[i])prime[cnt++]=i;for(j=0; j<cnt && prime[j]*i<=N; j++) { check[prime[j]*i]=1;if(i%prime[j]==0)break;}} }

?每次遇到未標記的素數就記錄,然后用當前的素數或合數與記錄下的素數表依次相乘。

藍色的這一句,保證了每個合數只被篩去一次(如下表),也是歐拉篩法優化的核心思想。

?  例如12 = 4*3 = 6*2,

  將它拆分成 (2*2)*3 和 (2*3)*2,

  因為素數之積顯然不是素數,所以在繼續篩的過程中一定會遇到2*3,

  說明4=2*2所篩掉的合數2*2*prime[i](除了prime[0]=2本身),一定會在以后重復算一次。

  那么先保留2的一列,3只要遇到2的倍數一定可以在2的一列出現,5只要遇到2、3的倍數一定可以在前兩列出現...

?

?

更新于19/2/11

在浙江集訓剛好學了這個qwq其實這個線性篩素數是這樣的,

因為當前枚舉的合數是i*pj,且pj|i(即i%pj=0),那么下一個枚舉的是i*pj+1,

因為i已經是pj的倍數了,那么i*任何正整數一定也是pj的倍數,

說明i*pj+1在后面一定會被更小的素數(pj)篩去。

?

轉載于:https://www.cnblogs.com/mogeko/p/10134838.html

總結

以上是生活随笔為你收集整理的Euler:欧拉函数&素数筛的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。