[原創(chuàng)][luogu]P1217 回文質數 真·生成回文的方法
不多說,直接看代碼,都在注釋里
// 中心思想:
// * 1. 代入數據只想回文的一半和位數的變化
// * 例. 1001 和 101 都存的是10, 但是位數一個是4, 一個是3
// * 2. 安裝只存一半的思想,進位時是從中心進位
// * 例. 1001 => 1111, 101 => 111
// * 例. 99 => 101, 999 => 1001
// * 3. 進位時存儲的方式
// * 例. 偶數進位后是奇數位的情況 (實際數字:9999 | 存儲數字:99 | 位數:4) => (實際數字:10001 | 存儲數字:100 | 位數:5)
// * 例. 奇數進位后是偶數位的情況 (實際數字:99999 | 存儲數字:999 | 位數:5) => (實際數字:100001 | 存儲數字:100 | 位數:6)
// * 例. 雖然都是進位,但是進位后的數字奇數時存儲數字會進一位,偶數時不會進位
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
using namespace std;
// 回文結構體
struct hui {
int w; // 位數
int n; // 回文的一半 奇數是w/2+1位 偶數是w/2位 如 1001為10, 101還是為 10
};
// 雙重循環(huán)判質數,基礎算法,就不注釋了
// 有人特判二的倍數,但是我覺得不必要,進循環(huán)第一個試的就是2,時間復雜度沒差多少
bool isZ(int n) {
if(n <= 1) {
return false;
}
for(int i=2; i*i<=n; i++) {
if(n%i==0) {
return false;
}
}
return true;
}
// 獲取參數x之后的第一個回文數
hui getFirst(int x) {
// 初始化
int a[10] = {}; // 存每一位的數組
hui t; // 要返回的回文數結構體
// log10求位數 注意!!! log10返回浮點數!!!
t.w = log10(x)+1;
// 考慮順序地拆解每一位 例如: 10是[1, 0]不是[0, 1]
for(int i=1; i<=t.w; i++) {
a[t.w-i] = x%10;
x /= 10;
}
// 這里是重點!!!
// 開始之前,先解釋一串表達式 t.w/2-1+(t.w&1)
// 這串表達式是找到回文的中心,偶數是靠前一點的中心
// 位數除以二是找到中心,減一是適配數組從0開始,(t.w&1)是用位運算判斷奇偶,奇數就返回1,偶數返回0,可以帶入幾個數試試
int i, j;
// 開始
i = 0;
// 結尾
j = t.w - 1;
// 左右兩邊向中心走(什么雙指針之類的
while(i<j) {
// 重點中的核心!!!
// 如果右邊的回文數比左邊的大就讓左邊進一
// 例如 23042 出來的是 23100 不是24042!
// 13出來的是20 不是33!
// 因為結構體只存回文的一半, 所以只搞好一半就行
if(a[i] < a[j]) {
a[t.w/2-1+(t.w&1)]++;
break;
}
i++;
j--;
}
// 搞好數組了就要存入結構體,例如 1001 存 10, 100001存 100,存一半 (10001也是存10但是它們結構體里位數不一樣
t.n = 0;
for(i = 0; i<t.w/2+(t.w&1); i++) {
t.n *= 10;
t.n += a[i];
}
return t;
}
// 下一個回文數
// 這個函數就是找規(guī)律
void nextHui(hui& x) {
int y = x.n;
x.n++;
// 是否進位
// 看文章開頭的中心思想
if(int(log10(x.n))+1 != int(log10(y))+1) {
if(x.w&1) {
x.n /= 10;
}
x.w++;
}
}
// 結構體轉int
int toInt(hui x) {
int s = x.n;
int t = x.n;
if(x.w&1) {
t /= 10;
}
while(t!=0) {
s *= 10;
s += t%10;
t /= 10;
}
return s;
}
int main() {
int start, end;
cin >> start >> end;
hui x;
x = getFirst(start);
// 沒到就枚舉
while(toInt(x) <= end) {
// 判斷質數
if(isZ(toInt(x))) {
cout << toInt(x) << endl;
}
// 下一個回文數
nextHui(x);
}
return 0;
}
本文來自博客園,作者:月神的使者,轉載請注明原文鏈接:http://www.rzrgm.cn/dffxd/p/17279748.html

浙公網安備 33010602011771號