題目描述
因為151既是一個質數又是一個回文數(從左到右和從右到左是看一樣的),所以 151 是回文質數。
寫一個程序來找出范圍[a,b](5 <= a < b <= 100,000,000)( 一億)間的所有回文質數;
輸入輸出格式
輸入格式:
第 1 行: 二個整數 a 和 b .
輸出格式:
輸出一個回文質數的列表,一行一個。
輸入輸出樣例
輸入樣例#1:
5 500
輸出樣例#1:
5 7 11 101 131 151 181 191 313 353 373 383
說明
Hint 1: Generate the palindromes and see if they are prime.
提示 1: 找出所有的回文數再判斷它們是不是質數(素數).
Hint 2: Generate palindromes by combining digits properly. You might need more than one of the loops like below.
提示 2: 要產生正確的回文數,你可能需要幾個像下面這樣的循環。
題目翻譯來自NOCOW。
USACO Training Section 1.5
產生長度為5的回文數:
for (d1 = 1; d1 <= 9; d1+=2) { // 只有奇數才會是素數
for (d2 = 0; d2 <= 9; d2++) { for (d3 = 0; d3 <= 9; d3++) { palindrome = 10000*d1 + 1000*d2 +100*d3 + 10*d2 + d1;//(處理回文數...) } } }
分析
求回文素數,如果枚舉所有的數,會很浪費時間,所以可以先構造出回文數,然后判斷是不是素數即可,
- 除11不存在偶數位的回文數是素數,因為該回文數能被11整除,也就說明大於11的滿足條件的回文數是奇數位,以中間數為對稱軸。
- 因大於2的素數都是奇數,故在奇數位回文數中,首位為2、4、6、8的數均不是素數。首位是它們,根據回文數的性質,末尾也是他們。
- 因5的任何倍數末尾為5,故在奇數位回文數中,首位為5的數均不是素數。
滿足以上條件,制造回文數。
因為回文數呈現對稱,所以構造時做多5位(一共99999個數),減去偶數一半,還剩不到5萬個,剩下的數中首位為0、2、4、5、6、8的數均不滿足條件,回文數最多為2W個。
構造出回文數后,在判斷是否滿足素數。
code
1 #include<cstdio> 2 #include<cmath> 3 #include<iostream> 4 #include<algorithm> 5 using namespace std; 6 7 int l,r,now = 2; 8 9 int Creatpalindrome(int n)//構造回文數 10 { 11 if (n<10)//小於10的會問素數只有2,3,5,7,兩位的只有11 12 { 13 switch(n) 14 { 15 case 2:now=3;return 2;//now遞進的,下一次調用函數時就會進行下一條語句 16 case 3:now=5;return 3; 17 case 5:now=7;return 5; 18 case 7:now=9;return 7; 19 case 9:now=10;return 11; 20 } 21 } 22 23 int wn = (int)(log(n*1.0)/log(10*1.0));//位數-1,以中間位對稱軸 24 int gn = n/(int)(pow(10*1.0,wn));//最高位是什么 25 int ret = 0; 26 //最高位2,4,6,8,5都不滿足條件,但它們+1就滿足,所以它們的最高位+1 27 switch (gn) 28 { 29 case 2: 30 case 4: 31 case 6: 32 case 8: 33 now = (gn+1)*(int)pow(10*1.0,wn);//最高位+1后的數 34 ret = now*(int)pow(10*1.0,wn)+(gn+1);//最后一位數要和最高位一樣 35 ++now; 36 return ret; 37 case 5: 38 now = 7*(int)pow(10*1.0,wn);//最高位是5就將它變成7 39 ret = now*(int)pow(10*1.0,wn)+7; 40 ++now; 41 return ret; 42 } 43 //最高位滿足條件 44 int sumn = 0; 45 //記錄n的前n-1位逆序和,比如12345的逆序和為4321,所以n 46 ret = n*(int)pow(10*1.0,wn); 47 n /= 10; 48 49 while (n) 50 { 51 sumn = sumn*10+n%10; 52 n /= 10; 53 } 54 ++now; 55 return ret+sumn; 56 } 57 bool Isprime(int x) 58 { 59 for (int i=3; i*i<=x; i+=2) 60 { 61 if (x%i==0) 62 return false ; 63 } 64 return true; 65 } 66 int main() 67 { 68 cin>>l>>r; 69 for (int i=l; i<=r; ) 70 { 71 i = Creatpalindrome(now); 72 if (i>=l&&i<=r&&Isprime(i)) 73 { 74 cout<<i<<endl; 75 } 76 } 77 return 0; 78 }