Problem Description
Eddy's interest is very extensive, recently he is interested in prime number. Eddy discover the all number owned can be divided into the multiply of prime number, but he can't write program, so Eddy has to ask intelligent you to help him, he asks you to write a program which can do the number to divided into the multiply of prime number factor .
 
Input
The input will contain a number 1 < x<= 65535 per line representing the number of elements of the set.
 
Output
You have to print a line in the output for each entry with the answer to the previous question.
 
Sample Input
11
9412
 
Sample Output
11
2*2*13*181
 
Author
eddy
 
 
题目大意的要求找出一个小于65535整数的几个素数相乘的结果
 
首先来看一篇关于素数的blog
 

质数的定义

一个数,如果只有和它本身两个因数,这样的数叫做质数,又称素数。

在上文《素数算法大全,及C程序实现优化详解 (一) 试除法》中我们已经探讨了求解素数的一类算法,并且将试除法从最初的低效版本优化的高效的V2。那么,还有没有其它更佳算法呢?这就是下面三藏要和大家探讨的内容

合数过滤筛选法

算法描述:我们知道,素数N不能被2~(N-1)间的任何数整除;反过来看,只要能被2~(N-1)间的任何数整除的N,都不是素数。所以我们可以采用一个简单的排除法:就是对N以内的所有数,只要逐个去除值为2~(N-1)的倍数的数,剩下的就是素数。

C语言实现

// 合数过滤筛选法 Ver1  // 参数:n 求解n以内(包括n)的素数 // 返回值:n以内素数个数  int CompositeNumFilterV1(int n) {  int i, j;  // 素数数量统计   int count = 0;  // 分配素数标记空间,结合后文思考为何+1  char* flag = (char*)malloc( n+1 );     // 初始化素数标记   for (i=2; i<=n; i++)  {   // 为什么*(p+i)要写成flag[i]呢?可读性更佳尔    flag[i] = 1;  }    // 写程序要注意排版和留空,方便阅读,也可减少出错几率  // 以2~(N-1)为因子过滤合数   for (i=2; i < n; i++)  {   for (j=2; i*j <= n; j++)   {    // i*j是由i,j两整数相乘而得,显然不是素数    flag[i*j] = 0;   }  }    // 统计素数个数  for (i=2; i<=n; i++)  {   // 其实if(flag)就其同样作用了,但这么写是有留言的    // 请参阅《C语言程序设计常见错误剖析及解决之道》一文    if (1 == flag[i]) count++;  }     // 因输出费时,且和算法核心相关不大,故略     // 释放内存,别忘了传说中的内存泄漏   free(flag);    return count; }

在上文给出的main函数中以不同参数调用CompositeNumFilterV1函数,得到执行结果如下:

[100000]以内素数个数:9592, 计算用时:毫秒 [1000000]以内素数个数:78498, 计算用时:毫秒 [5000000]以内素数个数:348513, 计算用时:毫秒 [10000000]以内素数个数:664579, 计算用时:毫秒

注:因程序是非独占性运行的,所以时间不是完全精确的,但基本能反映实情

显然,比上文中的试除法要快,而且谁都可以看到上例是一个未经优化的粗陋版本,好多地方是三藏故意采用比较低效做法,为了与后文的优化版比较,凸显优化之重要,也为了初学者记住别采用类似低效做法,下面我们开始优化之旅

优化分析

上面CompositeNumFilterV1函数存在的问题有:

1.在外层循环,需要一直执行到n-1吗?不要,因为n/2~n-1间的数显然不能整除n

2.在内层循环中重复使用i*j显然是低效的,考虑到计算机中加减运算速度比乘除快可以考虑变乘法为加法

3.在循环修改flag过程中,其实有很多数会被重复计算若干次,比如6=2*3=3*2,会被重复置,类似操作很多,所以我们得设法避免或减少flag重复置

据上述分析,我们可将程序优化如下:

// 合数过滤筛选法 Ver2  // 参数:n 求解n以内(包括n)的素数 // 返回值:n以内素数个数  int CompositeNumFilterV2(int n) {  int i, j;  // 素数数量统计   int count = 0;  // 分配素数标记空间,明白+1原因了吧,因为浪费了一个flag[0]  char* flag = (char*)malloc( n+1 );     // 初始化素数标记,要高效点咯  flag[2] = 1;  // 注意是i<n不是上例中的i<=n了,理由自思   for (i=3; i<n; i++)  {   flag[i++] = 1;   // 偶数自然不是素数,直接置好了    flag[i] = 0;  }  // n为奇数   if (n%2 != 0)  {   flag[n] = 1;  }    // 从开始filter,因为的倍数早在初始化时代就干掉了  // 到n/2止的理由还要说吗   for (i=3; i <= n/2; i++)  {   // i是合数,请歇着吧,因为您的工作早有您的质因子代劳了    if (0 == flag[i]) continue;      // 从i的倍开始过滤,变乘法为加法     for (j=i+i; j <= n; j+=i)   {    flag[j] = 0;   }  }    // 统计素数个数  for (i=2; i<=n; i++)  {   if (flag[i]) count++;  }     // 因输出费时,且和算法核心相关不大,故略     // 释放内存,别忘了传说中的内存泄漏   free(flag);    return count; }

再来调用CompositeNumFilterV2得到执行结果:

[100000]以内素数个数:9592, 计算用时:n太小,时间精度不够 [1000000]以内素数个数:78498, 计算用时:毫秒 [5000000]以内素数个数:348513, 计算用时:毫秒 [10000000]以内素数个数:664579, 计算用时:毫秒 [100000000]以内素数个数:5761455, 计算用时:毫秒

哇哇,比昨天的试除发快了好多倍,可见算法的威力,值得好好学习,别说学算法没用咯。

上例着那个计算一亿以内的素数只要约秒,应该算不错了,今天是否可以休息了呢?No,我们要追求极限!

int CompositeNumFilterV3(int n) {  int i, j;  // 素数数量统计   int count = 0;  // 分配素数标记空间,明白+1原因了吧,因为浪费了一个flag[0]  char* flag = (char*)malloc( n+1 );  // 干嘛用的,请仔细研究下文  int mpLen = 2*3*5*7*11*13;  char magicPattern[mpLen];  // 奇怪的代码,why,思考无法代劳,想!   for (i=0; i<mpLen; i++)  {   magicPattern[i++] = 1;   magicPattern[i++] = 0;   magicPattern[i++] = 0;   magicPattern[i++] = 0;   magicPattern[i++] = 1;   magicPattern[i] = 0;  }  for (i=4; i<=mpLen; i+=5)   magicPattern[i] = 0;  for (i=6; i<=mpLen; i+=7)   magicPattern[i] = 0;  for (i=10; i<=mpLen; i+=11)   magicPattern[i] = 0;  for (i=12; i<=mpLen; i+=13)   magicPattern[i] = 0;    // 新的初始化方法,将2,3,5,7,11,13的倍数全干掉  // 而且采用memcpy以mpLen长的magicPattern来批量处理   int remainder = n%mpLen;  char* p = flag+1;  char* pstop = p+n-remainder;  while (p < pstop)  {   memcpy(p, magicPattern, mpLen);   p += mpLen;  }  if (remainder > 0)  {   memcpy(p, magicPattern, remainder);  }  flag[2] = 1;  flag[3] = 1;  flag[5] = 1;  flag[7] = 1;  flag[11] = 1;  flag[13] = 1;    // 从开始filter,因为2,3,5,7,11,13的倍数早被kill了   // 到n/13止的,哈哈,少了好多吧  int stop = n/13;  for (i=17; i <= stop; i++)  {   // i是合数,请歇着吧,因为您的工作早有您的质因子代劳了    if (0 == flag[i]) continue;      // 从i的倍开始过滤   int step = i*2;   for (j=i*17; j <= n; j+=step)   {    flag[j] = 0;   }  }    // 统计素数个数  for (i=2; i<=n; i++)  {   if (flag[i]) count++;  }     // 因输出费时,且和算法核心相关不大,故略     // 释放内存,别忘了传说中的内存泄漏   free(flag);    return count; }

再看CompositeNumFilterV3执行结果:

[1000000]以内素数个数:78498, 计算用时:毫秒 [5000000]以内素数个数:348513, 计算用时:毫秒 [10000000]以内素数个数:664579, 计算用时:毫秒 [100000000]以内素数个数:5761455, 计算用时:毫秒

再次优化后速度提升了又一倍左右,三藏不禁有点满足了,睡觉也!

 #include<iostream>
//#include<algorithm>
const int MAX= ;
using namespace std; int prime[MAX+];
int flag[MAX]; void Get_Prime(int &count)//得到0~MAX内的所有素数
{
int i,j;
//memset(flag,true,sizeof(flag));
flag[]=;
for(i=;i<MAX;i++)
{
flag[i++]=true;
flag[i]=false;//所有偶数都不是素数
}
// MAX为奇数
if (MAX% != )//MAX不是偶数
{
flag[MAX] = true;
}
for(i= ;i<MAX/; i++)//在外层循环,不需要一直执行到MAX
//因为MAX/2~MAX-1间的数显然不能整除MAX
{
if(flag[i]== false) continue;
for(j=;i*j<MAX;i++)
{
flag[i*j]==false;
}
} for(i=;i<MAX;i++)
{
if(flag[i])
{
prime[count]=i;
count++;
}
} }
int main()
{
int cases;
int count=;
Get_Prime(count);
while(scanf("%d",&cases)!=EOF)
{
int flag=true;
for(int i=;i<count;i++)
{
while(cases%prime[i]==)
{
if(flag)
{
flag=false;
cout<<prime[i];
}
else
cout<<"*"<<prime[i];
cases/=prime[i];
}
if(cases==) break;
}
cout<<endl;
} }

HDOJ 1164 Eddy's research I的更多相关文章

  1. HDOJ 1164 Eddy's research I(拆分成素数因子)

    Problem Description Eddy's interest is very extensive, recently he is interested in prime number. Ed ...

  2. HDOJ 1164 Eddy's research

    上一篇已经讲了,但是转载别人的很乱,这里自己根据blog里面写的思路,重新写过了一个程序 #include <iostream> #include <malloc.h> #in ...

  3. hdu 1164:Eddy's research I(水题,数学题,筛法)

    Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  4. hdu 1164 Eddy's research I

    http://acm.hdu.edu.cn/showproblem.php?pid=1164 题意很简单,只是写代码的时候需要注意几个问题 一.筛选素数的时候记得用埃式筛选法,要是直接找可能会WA. ...

  5. HDU 1164 Eddy's research I

    题目链接 题意 : 给你一个数,让你用它的素数质因子表示出来. 思路 : 先打一下表,因为会有重复的质因子,所以从大到小开始找,并且找到一个之后不能就接着往下找,要再找一遍这个数. #include ...

  6. HDU 1164 Eddy's research I( 试除法 & 筛法改造试除法 分解整数 )

    链接:传送门 题意:给出一个整数 n ,输出整数 n 的分解成若干个素因子的方案 思路:经典的整数分解题目,这里采用试除法 和 用筛法改造后的试除法 对正整数 n 进行分解 方法一:试除法对正整数 n ...

  7. HDU 1164 Eddy&#39;s research I【素数筛选法】

    思路:将输入的这个数分成n个素数的相乘的结果,用一个数组存储起来.之后再输出就能够了 Eddy's research I Time Limit: 2000/1000 MS (Java/Others)  ...

  8. Eddy's research I

    Eddy's research I Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others ...

  9. HDU 1165 Eddy's research II(给出递归公式,然后找规律)

    - Eddy's research II Time Limit:2000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64 ...

随机推荐

  1. zoj1967 poj2570 Fiber Network (floyd算法)

    虽然不是最短路,但是询问时任意两点之间的信息都要知道才能回答,由此联想到floyd算法,只要都floyd算法的原理理解清楚了就会发现:这道题的思想和求任意两点之间的最短路的一样的,只不过是更新的信息不 ...

  2. poj3061 Subsequence&&poj3320 Jessica's Reading Problem(尺取法)

    这两道题都是用的尺取法.尺取法是<挑战程序设计竞赛>里讲的一种常用技巧. 就是O(n)的扫一遍数组,扫完了答案也就出来了,这过程中要求问题具有这样的性质:头指针向前走(s++)以后,尾指针 ...

  3. uva11609(组合数学,快速幂)

    先选人,再从这些人里选一个队长,方案总数:C(i,1)*C(n,i)(其中i从1到n)的总和. 这个公式显然不能在时限内暴力算出来,需要变形和推导出更简单的来. 用到组合数里面这个公式:C(n,k)* ...

  4. [leetcode]_Flatten Binary Tree to Linked List

    题目:将一棵二叉树履平成一个类似Linked-list的东西. 思路:该过程类似于二叉树的前序遍历,但是遍历代码,我处理不来参数的变化.没AC. -------->写的很好的解题博客 参考上述博 ...

  5. UVA - 1606 Amphiphilic Carbon Molecules (计算几何,扫描法)

    平面上给你一些具有黑或白颜色的点,让你设置一个隔板,使得隔板一侧的黑点加上另一侧的白点数最多.隔板上的点可视作任意一侧. 易知一定存在一个隔板穿过两个点且最优,因此可以先固定以一个点为原点,将其他点中 ...

  6. Windbg内核调试之一: Vista Boot Config设置

    Windbg进行内核调试,需要一些基本的技巧和设置,在这个系列文章中,我将使用Windbg过程中所遇到的一些问题和经验记录下来,算是对Kernel调试的一个总结,同时也是学习Windows系统内核的另 ...

  7. 如何用windbg分析内存泄露

    1.     必须在命令行中设置为要分析的进程打开用户堆栈信息:C:\Program Files\Debugging Tools for Windows (x64)>gflags.exe -i ...

  8. ThreadPoolTaskExecutor的配置解释

    ThreadPoolTaskExecutor的配置在网上找了很多解释没找到,看了下ThreadPoolExecutor的配置,名字差不多,应该含义也差不多.只不过ThreadPoolTaskExecu ...

  9. 2018年长沙理工大学第十三届程序设计竞赛 Dzzq的离散数学教室1

    Dzzq的离散数学教室1 链接:https://www.nowcoder.com/acm/contest/96/D来源:牛客网 zzq的离散数学教室1 时间限制:C/C++ 1秒,其他语言2秒 空间限 ...

  10. SQL属性第一个值不被选中,属性默认第一个值

    把 Please Choose Color 属性名设置为不可选的 UPDATE `products_attributes` SET `attributes_display_only` = '1' WH ...