2013-08-18 11:20:43

素数、最大公约数、最下公倍数、质因数分解都是与素数相关的,解决了素数的问题,其他的都可以此为基础求解。

小结:

  1. 求1到n之间的素数的基本方法是通过遍历2到sqrt(n),判断每个数是否是素数来得到,但这种方法效率很低;比较高效的解法是通过筛选法求解,如下面代码中函数GetPrimeUnderNBySieve;
  2. 最大公约数可通过GCD递归定理求解,通俗的说法就是辗转相除法,《算法导论》中有详细的说明;
  3. 最下公倍数可通过最大公约数得到,公式为:LCM(a,b) = a*b / GCD(a,b);
  4. 质因数分解可通过质数表得到,如下面代码中函数GetPrimeFactorByPrimeTable所示;
  5. 另外,最后一种因数分解代码是最简练的,如函数Decomposition所示:
 1 void Decomposition(int nNum)
 2 {
 3     for(int i=2;i<nNum;)
 4     {
 5         if(nNum % i == 0)
 6         {
 7             nNum = nNum /i;
 8             cout<<i<<",";
 9         }
10         else
11         {
12             i++;
13         }
14     }
15     if(1<nNum)
16         cout<<nNum<<endl;
17 }

注意几点:

  • 可以用乘法代替开方,进行循环结束的判断
i * i <= num

  • 删选法时,筛子的下标变化可以通过相加或相乘来实现,如下:

相乘:

 1 for (primeIndex = 2;primeIndex * primeIndex < number;++primeIndex)
 2     {
 3         if (primeFlagArray[primeIndex])
 4         {
 5             for (sieveIndex = 2;sieveIndex * primeIndex <= number;++sieveIndex) //sieveIndex * primeIndex <= number
 6             {
 7                 primeFlagArray[sieveIndex * primeIndex] = false;
 8             }
 9         }
10     }

相加:

 1 for (primeIndex = 2;primeIndex * primeIndex < number;++primeIndex)
 2     {
 3         if (primeFlagArray[primeIndex])
 4         {
 5             for (sieveIndex = primeIndex + primeIndex;sieveIndex <= number;sieveIndex += primeIndex) //sieveIndex * primeIndex <= number
 6             {
 7                 primeFlagArray[sieveIndex] = false;
 8             }
 9         }
10     }

代码(包含测试,暂时没有发现错误,欢迎交流指正!):

  1 #include <iostream>
  2 #include <cassert>
  3 #include <cmath>
  4 using namespace std;
  5
  6
  7 //显示数组元素
  8 void DisplayArray(size_t *array,size_t len)
  9 {
 10     assert(array != NULL);
 11     for (size_t index = 0;index < len;++index)
 12     {
 13         cout<<array[index]<<"\t";
 14     }
 15     cout<<endl;
 16 }
 17
 18 //判断一个数是否为质数
 19 bool IsPrime_basic(size_t num)
 20 {
 21     assert(num >= 2);
 22     for (size_t i = 2;i < num;++i)
 23     {
 24         if (num % i == 0)
 25         {
 26             return false;
 27         }
 28     }
 29     return true;
 30 }
 31
 32 //判断一个数是否为质数
 33 bool IsPrime_improve(size_t num)
 34 {
 35     assert(num >= 2);
 36     //for (size_t i = 2;i < sqrt(num);++i) // ambiguous call to overloaded function
 37     for (size_t i = 2;i < (int)sqrt((double)num);++i)
 38     {
 39         if (num % i == 0)
 40         {
 41             return false;
 42         }
 43     }
 44     return true;
 45 }
 46
 47 //判断一个数是否为质数
 48 bool IsPrime(size_t num)
 49 {
 50     assert(num >= 2);
 51     for (size_t i = 2;i * i <= num;++i)  //i * i <= num而非i * i < num
 52     {
 53         if (num % i == 0)
 54         {
 55             return false;
 56         }
 57     }
 58     return true;
 59 }
 60
 61 //用筛选法求素数
 62 size_t GetPrimeUnderNBySieve(size_t number,size_t *primeArray)
 63 {
 64     assert(primeArray != NULL);
 65
 66     size_t primeIndex = 0;
 67     size_t sieveIndex = 0;
 68     size_t primeCounter = 0;
 69     bool *primeFlagArray = new bool[number + 1];//number + 1
 70     size_t index;
 71
 72     for (index = 2;index <= number;++index)  //index从2开始,而非从0开始;index <= number,而非index < number
 73     {
 74         primeFlagArray[index] = true;
 75     }
 76
 77     //memset(primeFlagArray,1,sizeof(bool) * number);
 78
 79     for (primeIndex = 2;primeIndex * primeIndex < number;++primeIndex)
 80     {
 81         if (primeFlagArray[primeIndex])
 82         {
 83             for (sieveIndex = 2;sieveIndex * primeIndex <= number;++sieveIndex) //sieveIndex * primeIndex <= number
 84             {
 85                 primeFlagArray[sieveIndex * primeIndex] = false;
 86             }
 87         }
 88     }
 89
 90     for (index = 2;index <= number;++index)    //index <= number
 91     {
 92         if (primeFlagArray[index])
 93         {
 94             primeArray[primeCounter++] = index;
 95         }
 96     }
 97     delete [] primeFlagArray;
 98     return primeCounter;
 99 }
100
101 //用筛选法求素数
102 size_t GetPrimeUnderNBySieve_2(size_t number,size_t *primeArray)
103 {
104     assert(primeArray != NULL);
105
106     size_t primeIndex = 0;
107     size_t sieveIndex = 0;
108     size_t primeCounter = 0;
109     bool *primeFlagArray = new bool[number + 1];//number + 1
110     size_t index;
111
112     for (index = 2;index <= number;++index)  //index从2开始,而非从0开始;index <= number,而非index < number
113     {
114         primeFlagArray[index] = true;
115     }
116
117     //memset(primeFlagArray,1,sizeof(bool) * number);
118
119     for (primeIndex = 2;primeIndex * primeIndex < number;++primeIndex)
120     {
121         if (primeFlagArray[primeIndex])
122         {
123             for (sieveIndex = primeIndex + primeIndex;sieveIndex <= number;sieveIndex += primeIndex) //sieveIndex * primeIndex <= number
124             {
125                 primeFlagArray[sieveIndex] = false;
126             }
127         }
128     }
129
130     for (index = 2;index <= number;++index)    //index <= number
131     {
132         if (primeFlagArray[index])
133         {
134             primeArray[primeCounter++] = index;
135         }
136     }
137     delete [] primeFlagArray;
138     return primeCounter;
139 }
140
141 //用递归法求GCD
142 size_t GetGCDByRecursion(size_t a,size_t b)
143 {
144     if (b ==0)
145     {
146         return a;
147     }
148
149     return GetGCDByRecursion(b,a % b);
150 }
151
152 //用循环求GCD
153 size_t GetGCDByIteration(size_t a,size_t b)
154 {
155     size_t aTmp = 0;
156     while (b != 0)
157     {
158         aTmp = a;
159         a = b;
160         b = aTmp % b;
161     }
162
163     return a;
164 }
165
166 //用GCD求LCM,LCM(a,b) = a*b / GCD(a,b)
167 size_t GetLCM(size_t a,size_t b)
168 {
169     return ( (a * b) / GetGCDByRecursion(a,b) );
170 }
171
172 //求一个质数的下一个质数
173 size_t GetNextPrime(size_t currentPrime)
174 {
175     int curNum = currentPrime + 1;
176     while ( !IsPrime(curNum) )
177     {
178         ++curNum;
179     }
180     return curNum;
181 }
182
183 //根据质数表求质因数分解
184 void GetPrimeFactorByPrimeTable(size_t num,size_t *primerFactor,size_t *pCnt)
185 {
186     *pCnt = 0;
187     if ( IsPrime(num))
188     {
189         primerFactor[(*pCnt)++] = num;
190         return;
191     }
192
193     size_t *primeArray = new size_t[num];
194     size_t primeCounter = 0;
195     primeCounter = GetPrimeUnderNBySieve_2(num,primeArray);
196
197     cout<<"the number of primes under "<<num<<" is :"<<primeCounter<<",they are :"<<endl;
198     DisplayArray(primeArray,primeCounter);
199
200     assert(primeCounter <= num);
201     size_t index = 0;
202
203     //for (index = 2;index * index < num;++index)
204     //while (index < primeCounter)
205     while (primeArray[index] <= num)
206     {
207         if (num % primeArray[index] == 0)
208         {
209             primerFactor[(*pCnt)++] = primeArray[index];
210             num = num / primeArray[index];
211             index = 0;
212
213             //if ( IsPrime(num))
214             //{
215             //    primerFactor[(*pCnt)++] = num;
216             //    return;
217             //}
218         }
219         else
220         {
221             ++index;
222         }
223     }
224
225     delete [] primeArray;
226 }
227
228 //质数为自然数,所以此处的输入num为不小于最小质数2的自然数
229 //输入参数:num,待处理数字
230 //    primerFactor,存放num的质因数的数组的首地址
231 //    pCnt,存放数组长度的空间的地址
232 void GetPrimeFactor(size_t num,size_t *primerFactor,size_t *pCnt)
233 {
234     assert(num >= 2);
235     *pCnt = 0;
236     const size_t MinPrime = 2;
237     size_t currentPrime = 0;
238     while ( !IsPrime(num)  )
239     {
240         currentPrime = MinPrime;
241         while (num > currentPrime )  //num 不可能等于 currentPrime ,因为有外层while条件的保证
242         {
243             if (num % currentPrime == 0)  //从最小的质数开始,判断是否为num的因数,若不是判断下一个质数
244             {
245                 primerFactor[(*pCnt)++] = currentPrime;
246                 num = num / currentPrime;
247                 break;
248             }
249             else
250             {
251                 currentPrime = GetNextPrime(currentPrime);  //求当前质数的下一个质数
252             }
253         }
254     }
255     primerFactor[(*pCnt)++] = num;  //写入最后一个质因数
256 }
257
258 //直接求质因数分解
259 void Decomposition(int nNum)
260 {
261     for(int i=2;i<nNum;)
262     {
263         if(nNum % i == 0)
264         {
265             nNum = nNum /i;
266             cout<<i<<",";
267         }
268         else
269         {
270             i++;
271         }
272     }
273     if(1<nNum)
274         cout<<nNum<<endl;
275 }
276
277 //测试
278 void TestGetPrimeUnderN()
279 {
280     size_t number = 0;
281     size_t *primeArray = NULL;
282     size_t primeCounter = 0;
283     cout<<"TestGetPrimeUnderN..."<<endl;
284     cout<<"please enter a number(end with ctrl + z)"<<endl;
285     while (cin>>number)
286     {
287         primeArray = new size_t[number];
288         //primeCounter = GetPrimeUnderNBySieve(number,primeArray);
289         primeCounter = GetPrimeUnderNBySieve_2(number,primeArray);
290         cout<<"the number of primes under "<<number<<" is :"<<primeCounter<<",they are :"<<endl;
291         DisplayArray(primeArray,primeCounter);
292         cout<<"please enter a number(end with ctrl + z)"<<endl;
293         delete [] primeArray;
294     }
295 }
296
297 void TestGetGCDAndLCM()
298 {
299     size_t a = 0;
300     size_t b = 0;
301
302
303     cout<<"TestGetGCD..."<<endl;
304     cout<<"please enter two numbers(end with ctrl + z)"<<endl;
305     while (cin>>a>>b)
306     {
307         cout<<"(GetGCDByRecursion)the GCD of "<<a<<" and "<<b<<" is : "<<GetGCDByRecursion(a,b)<<endl;
308         cout<<"(GetGCDByIteration)the GCD of "<<a<<" and "<<b<<" is : "<<GetGCDByIteration(a,b)<<endl;
309         cout<<"the LCM of "<<a<<" and "<<b<<" is : "<<GetLCM(a,b)<<endl;
310         cout<<"please enter two numbers(end with ctrl + z)"<<endl;
311     }
312 }
313
314 //测试代码
315 void TestDriverGetPrimeFactor()
316 {
317     const size_t MaxNumberOfPrimeFactor = 100;
318     size_t primerFactor[MaxNumberOfPrimeFactor];
319     size_t Cnt = 0;
320     //size_t *pCnt = &Cnt;   //不能不定义Cnt,而直接用*pCnt
321     size_t num;
322
323     cout<<"please enter a number(end with ctrl + z)"<<endl;
324     while (cin>>num)
325     {
326         //GetPrimeFactor(num,primerFactor,pCnt );
327         GetPrimeFactorByPrimeTable(num,primerFactor,&Cnt);
328         cout<<"the prime factor of number "<<num<<" is :"<<endl;
329         DisplayArray(primerFactor,Cnt);
330
331         Decomposition(num);
332         cout<<"please enter a number(end with ctrl + z)"<<endl;
333     }
334 }
335
336 //main
337 int main()
338 {
339     TestDriverGetPrimeFactor();
340     //TestGetPrimeUnderN();
341     //TestGetGCD();
342     return 0;
343 }

转载于:https://www.cnblogs.com/youngforever/p/3265790.html

素数、最大公约数、最下公倍数、质因数分解相关推荐

  1. 水仙花数素数质因数分解的C语言实现

    最近,我翻了一下之前的C语言教材,看了三个有意思的小程序,包括:寻找"水仙花数".判断某数是否为素数.对一个数进行质因数分解.我想把这三个东西放到一个程序中,便写下了此文. 算法步 ...

  2. c语言素数筛法与分解素因数,质因数分解及代码:

    计算方法 短除法 求一个数分解质因数,要从最小的质数除起,一直除到结果为质数为止.分解质因数的算式的叫短除法,和除法的性质差不多,还可以用来求多个个数的公因式: 求最大公因数的一种方法,也可用来求最小 ...

  3. 素数判定质因数分解(数论)(Miller Rabin)(Pollard Rho)

    太玄学了! 我真的被概率的魅力折服了.此前我认为1便是1,0.9999999999-便是0.9999999999-. 但实际上它们有着千丝万缕的关系. 试想,如果一件事发生的概率是0.99999999 ...

  4. C++判断是否为素数、求一个数的因数、质因数分解

    判断一个数是否为素数 #include<iostream> #include<vector> #include<math.h> #include<algori ...

  5. 质因数分解及算法实现

    每个合数都可以写成几个质数相乘的形式,这几个质数就都叫做这个合数的质因数.如果一个质数是某个数的因数,那么就说这个质数是这个数的质因数.而这个因数一定是一个质数. 定义 质因数(或质因子)在数论里是指 ...

  6. 利用o(nlogn)的时间复杂度对某一个区间进行质因数分解

    这道题我们得用素数筛,到不是要判断某个数是否是质数,而是要在计算素数的过程中算出每一个数的最小质因数,对素数筛有这个功能! 首先我们看素数筛的步骤: 我们设计一个bool数组prime[N],prim ...

  7. 【Python】对大数质因数分解的算法问题

    [Python]对大数质因数分解的算法问题 发现问题 尝试分析 最后 我的代码(C1) 百科代码(C2) 发现问题   我是一个初学者,在编写一个分解质因数的代码时,学习到了 Miller-Rabin ...

  8. Miller_Rabbin算法判断大素数,Pollard_rho算法进行质因素分解

    Miller-rabin算法是一个用来快速判断一个正整数是否为素数的算法.它利用了费马小定理,即:如果p是质数,且a,p互质,那么a^(p-1) mod p恒等于1.也就是对于所有小于p的正整数a来说 ...

  9. [数论] Miller_Rabbin算法判断大素数,Pollard_rho算法进行质因素分解

    讲解转载于:http://www.cnblogs.com/rainydays/archive/2011/09/01/2162049.html   http://blog.sina.com.cn/s/b ...

最新文章

  1. SUBMIT 的使用方法
  2. 双目立体匹配经典算法之Semi-Global Matching(SGM)概述:匹配代价计算之互信息(Mutual Information,MI)...
  3. js实现简单的图片轮播
  4. ITK:处理点和单元数据
  5. Lucene6去掉了Filter但是可以用BooleanQuery实现Filter查询
  6. TensorFlow 支持 Unicode,中文 NLP 终于省心了
  7. [转载]MySQL锁机制
  8. 他们为啥说我没有数据分析思维?
  9. 由浅入深了解EventBus:(五)
  10. ​24小时企业级微信小程序全套开发视频教程
  11. Android APP完整基础教程(01)开发环境简介
  12. Android信任Https自签名证书详细教程
  13. 金融衍生品软件产品设计必备知识——外汇相关知识
  14. 通过HDMI获取显示器EDID数据
  15. QT如何实现二级下拉菜单(Combo box)
  16. 微云直链解析php,用微云做直链
  17. 蒲公英音乐种子计划海选招募正式启动
  18. 【论文笔记】用数字孪生改变农业食品生产系统和供应链
  19. teablue数据分析_大数据丨2016-2017年美国茶叶消费市场分析与展望
  20. [RK3568 Android11] 开发之开发者选项中添加USB OTG模式切换(一)

热门文章

  1. php多选框怎么传值,tp3.2如何处理多选框传参和判断状态
  2. oracle表中怎么去重复,Oracle里去掉表里组合字段重复的记录步骤是什么呢?
  3. python数据分析设置_Python 数据分析系列之如何安装和设置 Python
  4. iis伪静态排除css_魔众系统伪静态规则怎么配
  5. spring 框架学习(一)
  6. 实现对学生表的删除操作
  7. python可视化窗口制作一个摇骰子游戏_使用python制作一个抽奖小游戏——骰子游戏...
  8. 1小时学会:最简单的iOS直播推流(二)代码架构概述
  9. 微信小程序云开发图片上传完整代码附效果图
  10. 04-dispatch_group