poj3126
来源:互联网 发布:do not tag 淘宝网 编辑:程序博客网 时间:2024/06/05 17:20
这道题目的考查点有两个,第一:筛法求素数,第二:广搜。首先简单介绍一下筛法求素数的算法及性能优化。筛法求素数的理论是:任何素数的倍数一定是合数,这是显而易见的。那么筛法求素数的核心就是利用已求出的素数将合数筛掉,这样会极大的增强朴素算法的效率。对了,朴素算法如下:
int pivot=0;int prime[110];for(i=2;i<=n;i++){for(j=2;j<=int(sqrt(double(i)));j++)if(i%j==0)break;if(j>int(sqrt(double(i)))prime[pivot++]=i;}
时间复杂度为n^3/2,小于等于n的每一个数都要判定是否为素数,然后进数组。该算法很明显低效率。第一步优化可以这样考虑:将偶数都删除(偶数不是素数),从3开始枚举。外层循环为i+2,这样就降低了将近一半的时间复杂度。第二步优化就是最普通的筛法求素数了,下面是代码:
<p>memset(flag,1,sizeof(flag));for(int i=2;i<=int(sqrt(double(n)));i++) if(flag[i]){ for(int j=i+i;j<=n;j+=i) if(j%i==0) flag[j]=0; } pivot=0;for(int i=2;i<=n;i++) if(flag[i]) prime[++pivot]=i;</p><p> </p>
这样的时间复杂度为接近为O(N),更优化的还可以实现将偶数给除去,数组中只保存奇数,比如数组下标0对应于3,1对应于5,。。。。。n对应于2*n+3。这样就可以减少一半以上的时间复杂度了。目前最优化的筛法求素数还可以进一步优化。每一次筛掉不是素数的奇数时都是从数组下标为i+1开始试探,这样可能会导致许多无用的筛除操作。我们希望每一次从应该开始筛除的位置进行筛除操作。这样通过不断的观察与验证我们发现:每次从(2*i+6)*i+3开始,才不会导致无用的筛除操作(当然不能绝对避免重复筛除的操作,只是非常少了)这样以后时间复杂度降低为0(logn),下面是算法:
int index=0;for(int i=3;i<=n;i++)if(i%2!=0){init[index]=i;flag[index++]=1;}for(int i=0;init[i]<=int(sqrt(double(n)));i++)if(flag[i]){for(int j=(2*i+6)*i+3;j<index;j++)if(init[j]%init[i]==0)flag[j]=0;}pivot=0;prime[0]=2;for(int i=0;i<index;i++)if(flag[i])prime[pivot++]=init[i];
筛法求素数就介绍到这里,筛法求素数掌握了,这题就是一广搜水题了,只是要注意几个问题:
1)题目要求n,m都是四位素数(无前导0)
2)从n到m的素数path不一定要递增,只要满足是四位素数并且相领素数有且只有一位不同,实际上n不一定比m要小,这也证明了这点。
3)每一次变换都要有一个代价,不管是不是相同数字的变换(比如都是个位上的0换成1)
下面是代码: 204K+172MS
#include <stdio.h>#include <stdlib.h>#include <string.h>#include <math.h>#define Max 10010bool flag[Max];bool vi[Max];int init[Max];int prime[Max];int pnum;int n,m;int Case;int time;struct Node{int value;int deep;}node[Max];void Get_prime(){int index=0;for(int i=3;i<=10000;i++)if(i%2!=0){init[index]=i;flag[index++]=1;}for(int i=0;init[i]<=int(sqrt(double(10000)));i++)if(flag[i]){for(int j=(2*i+6)*i+3;j<index;j++)if(init[j]%init[i]==0)flag[j]=0;}pnum=-1;for(int i=0;i<index;i++)if(flag[i] && init[i]>1000 && init[i]<=10000)prime[++pnum]=init[i];}bool Is_dif(int n,int m){int Sum=0;int temp1,temp2;while(n!=0){temp1=n%10;temp2=m%10;if(temp1!=temp2)Sum++;n/=10;m/=10;}if(Sum==1)return true;return false;}bool bfs(){ // for(int i=0;i<=pnum;i++)//printf("%d ",prime[i]);memset(vi,0,sizeof(vi));int pivot=0;node[pivot].value=n;node[pivot].deep=0;int index=0;struct Node temp;vi[n]=1;while(index<=pivot){temp=node[index];//printf("%d\n",temp.value);if(temp.value==m){time=temp.deep;return true;}for(int i=pnum;i>=0;i--)if(!vi[prime[i]] && Is_dif(prime[i],temp.value)){ vi[prime[i]]=1;node[++pivot].value=prime[i]; node[pivot].deep=temp.deep+1;}index++;}return false;}int main(){scanf("%d",&Case);while(Case--){scanf("%d%d",&n,&m);Get_prime();if(bfs())printf("%d\n",time);elseprintf("Impossible\n");}return 0;}
- poj3126
- POJ3126
- poj3126
- poj3126
- poj3126
- POJ3126
- poj3126
- poj3126
- poj3126
- poj3126
- poj3126
- poj3126
- poj3126
- POJ3126
- Poj3126
- poj3126
- poj3126
- POJ3126
- Eclipse--关于添加用户库的那些事
- linux下软链接与硬链接 ln命令
- Ubuntu 14.04, Fedora 20, CentOS 6.5 下Broadcom4313网卡驱动安装以及上网问题
- Android APK反编译详解(附图)
- 卸载mathtype后,取消加载mathtype模板
- poj3126
- 专业IT人和非专业IT人的对比
- 《Javascript高级程序设计》第七章——函数表达式学习笔记
- Intent Flag介绍 intent.addFlags()
- PHP 之 继承
- Windows 中不规则窗体的编程实现三种方法:CRgn,作图路径法,据图像创建region
- 基于bootstrap的分页插件bootstrap-paginator
- OCP 1Z0 051 104
- cocos2d-x入门学习(四)跨版本代码移植实例之【微信飞机大战】