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;}


 

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 5个月宝宝吃奶少怎么办 26岁的1型糖尿病怎么办 睡前吃得太饱怎么办 胰岛素2小时>300怎么办 血清c肽测定高怎么办 体测蛋白质和骨骼肌偏高怎么办 半个月重了十斤怎么办 月经停了2个月怎么办 在练腹肌中腹痛怎么办 越练肌肉越肥怎么办 喘不过气来 心闷怎么办 被气得喘不过气怎么办 健身完头晕想吐怎么办 吃多了反胃头晕怎么办 合同未约定退货货物积压怎么办 运动内衣把胸压平怎么办 经常穿皮鞋脚臭怎么办 买衣服胸围小了怎么办 内衣下胸围太紧怎么办 穿文胸衣服要开怎么办 运动内衣的拉链老来怎么办 胸罩没干急着穿怎么办 跑步时大腿很痒怎么办 胖大腿内侧磨伤怎么办 内衣围带过松怎么办 内衣底围特别紧怎么办 全棉衣服上的油怎么办 高腰牛仔裤腰大了怎么办 新买衣服太硬怎么办 棉麻的衣服发硬怎么办 新衣服太硬怎么办雪纺 衣服硬的咯人怎么办 脖子上的勒痕怎么办 腿上容易出现勒痕怎么办 身上总有内裤印怎么办 内裤穿出了印怎么办 饮水机热水口不出水怎么办 饮水机热水口出水小怎么办 新饮水机热水口出水小怎么办 白钢水桶中间支撑怎么办 17岁想长高应该怎么办