HDU-1431(素数回文)(思维)(dfs+素数判定)

7 篇文章 0 订阅
2 篇文章 0 订阅

HDU-1431(素数回文)

素数回文

Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 16595    Accepted Submission(s): 3702


Problem Description
xiaoou33对既是素数又是回文的数特别感兴趣。比如说151既是素数又是个回文。现在xiaoou333想要你帮助他找出某个范围内的素数回文数,请你写个程序找出 a 跟b 之间满足条件的数。(5 <= a < b <= 100,000,000);
 

Input
这里有许多组数据,每组包括两组数据a跟b。
 

Output
对每一组数据,按从小到大输出a,b之间所有满足条件的素数回文数(包括a跟b)每组数据之后空一行。
 

Sample Input
  
  
5 500
 

Sample Output
  
  
5 7 11 101 131 151 181 191 313 353 373 383

刚开始就感觉这道题有点麻烦。起初的思路是先打素数表,再从素数中查找符合条件的回文数。感觉会超时,5 <= a < b <= 100,000,000,由于范围比较大,于是就单单测试了一下打表,结果在编译器上就运行了2~3秒,按照这样的思路写最终肯定会超时。于是想了很久发现可以利用回文数的对称性为切入点,可能还有解决的希望。

(先找出回文数,再判断是不是素数)

例:样例:5   500

首先 ;

一位数字:   2、3、5、7

       两位:  11  

      三位:   101   131    151

  如果是奇数位:通性:  ........x y z x y......(对称)

以:x y z x y为例,只需变化3个就可以了,x、y、z分别取值0~9(dfs)就可以打印出5位数的全部回文数,然后再对回文数判断是不是素数

如果是偶数位:通性:  .......x y z z y x......(对称)

以:x y z z x y为例,只需变化3个就可以了,x、y、z分别取值0~9(dfs)就可以打印出6位数的全部回文数,然后再对回文数判断是不是素数

就样例而言:

先打印  1 位的回文数,再打印 2 位的回文数,再打印 3 位 的回文数。。。。。。。。

该题思路:( for循环 + ( dfs + 素数判断 ) ),(for循环控制位数,dfs控制打印回文数,prim进行素数判断)

My  solution:

/*2016.3.31*/

#include<stdio.h>
#include<algorithm>
#include<string.h>
#include<math.h>
using namespace std;
int map[100000030],cnt1,cnt2,a1[20],k1,k2,vis;
int prim(int t)//判断素数 
{
	int i,j,k;
	for(i=2;i*i<=t;i++)
	{
		if(t%i==0)
		return 0;
	}
	if(t==1)//1不是素数,这点容易遗忘 
	return 0;
	return 1;
}
void dfs(int t1,int t2)
{
	int i,j,k,sum;
	if(t2<t1)//此次查询完成 
	{
		if(a1[vis]%2)//优化,最后一位数字如果是偶数的话,这个数肯定是偶数,不是素数 (同时巧妙化解了首位数字不能为0的情况)
		{
			sum=0;
			for(i=1;i<=vis;i++)//把这个数在数组中的数值位转换为整数sum 
			{
				sum=a1[i]+sum*10;
			}
			if(prim(sum)&&(sum>=k1&&sum<=k2))//sum不仅要是素数,而且还得大于等于a小于等于b 
			printf("%d\n",sum);
			return ;
		}
		return ;
	}
	for(i=0;i<=9;i++)//控制每个数值位上的数字 
	{
		a1[t1]=a1[t2]=i;//由于对称,所以相等 
		dfs(t1+1,t2-1);//左右各往里缩进一位 ,这一步特别重要 
	}
}
int main()
{
	int i,j,k,n,m,a,b;
	while(scanf("%d%d",&k1,&k2)==2)
	{
		a=k1;b=k2;
		cnt1=cnt2=0;
		while(b)
		{
			b=b/10;
			cnt2++;//cnt2记录b的位数 
		}
		while(a)
		{
			a=a/10;
			cnt1++;//cnt1记录a的位数 
		}
		for(i=cnt1;i<=cnt2;i++)//控制位数 
		{
			vis=i;//vis记录当前查询的最大位数 
			dfs(1,i);//在当前位数中,查找满足题目要求的回文素数 
		}
		printf("\n");	
	}
	return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值