【PAT笔记】数学问题——素数和质因数
1 素數
1.1 素數的判斷
素數的判斷較為簡單,直接上代碼,需要注意的幾點:
bool isPrime(int n){if(n==1) return false; //1需要特判int sqr=(int)sqrt(n*1.0); //之所以要用這條語句而不是在for循環里使用sqrt(n),解釋如下for(int i=2;i<=sqr;i++){if(n%i==0) return false;}return true; }在上面的代碼中,其中需要用到一條? int sqr=(int)sqrt(n*1.0); 用來在循環中做一個循環邊界呢。首先可以從 double sqrt(double) 可以看出,sqrt()的返回值和參數都是double類型的。在計算機中,小數都是不精確的,如,sqrt(9)是等于3.000000000001還是2.999999999999都是不好講的。有的計算機可能給出前者,有的則可能是后者,這樣對我們循環的邊界的判斷造成了影響。于是就用到了上面一行代碼,轉化參數的數據類型,保證sqrt得到我們想要的值。
1.2 素數表的獲取?
下面給出兩個方法。
首先是比較常用的,對n不超過是可以的,復雜度包括了判斷是否為素數O()和遍歷從1到n的復雜度O(n),因此第一種方式(對n不超過)的時間復雜度為O(n) 。下面給出代碼:
const int maxn=101; int Prime[maxn],pNum=0; //數組Prime()存放所有的素數,pNum為素數的個數 bool p[maxn]={0}; void Find_Prime(){for(int i=1;i<maxn;i++){if(isPrime(i)==true){ //判斷是否為素數Prime[pNum++]=i;p[i]=true;}} }其次是時間復雜度更小的一種方式,為O(),這是一種什么原理的,我們來看:
由上面可以看出,當從小到大達到達到某數n的時候,如果n沒有被前面的步驟篩去,那么n就一定是素數。原理是:當n不是素數時,必然有小于n的質因數,這樣在之前篩去質因數的倍數的時候就應該把n篩去了。所以,當n沒有被前面步驟篩去的時候,就一定是一個素數。于是可以給出如下代碼:
const int maxn=101; int Prime[maxn],pNum; //同樣的道理,建立一個數組Prime來存放素數,pNum為蘇數的個數 bool p[maxn]={0}; //素數為0,非素數為1 void Find_Prime(int n){for(int i=2;i<max;i++){if(p[i]==0){Prime[pNum++]=i;for(int j=i;j<maxn;j += i){p[j]=true;}}} }2 質因數的分解
質因數分解就是將一個整數n分解成若干個素數乘積的形式,如8=222,18=2233等等。素數的尋找上面已經講過了,而且值得注意的是2357111317192329的積就已經超過了int型的上限了。
我們對于質因數的分解,不妨先設一個結構體:
struct factor{int x,cnt; //x代表了質因數,cnt代表了該質因數的個數 }fac[10];那么對于180來說,就有
fac[0].x=2; fac[0].cnt=2;fac[1].x=3; fac[1].cnt=2;fac[2].x=5; fac[2].cnt=1;?首先枚舉1~sqrt(n)范圍內所有質因子p,判斷p是否為n的質因數。
const num=0; void Find_Factor(int n){for(int i=0;i<10;i++){if(n%Prime[i]==0){fac[num].x=Prime[i];fac[num].cnt=0;while(n%fac[num].x==0){fac[num].cnt++;n=n/fac[num].x;}num++;}} }?如果在上邊步驟結束后n人大于1,說明n有且僅有一個質因子(即n本身),這時需要將這個質因子加入fac數組,令其個數為1.
if(n!=1){fac[num].x=n;fac[num++].cnt=1; }?解釋完畢
總結
以上是生活随笔為你收集整理的【PAT笔记】数学问题——素数和质因数的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 【PAT笔记】C++标准模板库STL(二
- 下一篇: 【计算机网络(微课版)】第1章 概述 课