HDU-1431(素數迴文)
素數迴文
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 16595 Accepted Submission(s): 3702
剛開始就感覺這道題有點麻煩。起初的思路是先打素數表,再從素數中查找符合條件的迴文數。感覺會超時,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;
}