小红帽的回文数
小红帽的回文数
题解:
对于一个数\(a[i]\) , \(a[i] + 1\)进制一定能使它成为回文串,\(a[i] - 1\)进制也一定能使它成为回文串, (例如: \(8\), 在\(9\)进制下是\(8\),在\(7\)进制下为\(11\)),所以进制\(x\leq a[i] + 1\) 。
当进制数超过了\(\sqrt{a[i]}\)之后, \(a[i]\)进制转换得到的数字一定是两位数, (可以举几个例子, 如:\(16\)的\(5\)进制数是\(31\),\(4\)的\(3\)进制数是\(11\)),因为当进制是\(\sqrt{a[i]}\)时,正好为\(100\), 如果进制数\(x\)超过了\(\sqrt{a[i]}\),有第三位的话,这个数至少表示的是 $ x ^ 2$,是不成立的。
当$x > \sqrt{a[i]} \(时, 可以设转化后的回文数的两位数均为\)b$(因为是回文串),
\(a[i] = b * x + b\)
\(a[i] = b * (x + 1)\)
\(x = a[i]/b - 1\)
当$x \leq \sqrt{a[i]} \(时,暴力枚举\)x$。
#include <cstdio>
#include <iostream>
#include <cmath>
#define orz cout << "AK IOI" <<"\n"
#define int long long
using namespace std;
const int maxn = 1010;
inline int read()
{
int x = 0, f = 1;
char ch = getchar();
while (ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0';ch = getchar();}
return x * f;
}
int n, a, number[10000000];
bool judge(int num, int x)
{
int cnt = 0;
while(num > 0)
{
number[++cnt] = num % x;
num /= x;
}
int mid;
if(cnt % 2 == 1) mid = (cnt - 1) / 2;
else mid = cnt / 2;
for(int i = 1; i <= mid; i++)
if(number[i] != number[cnt - i + 1]) return 0;
return 1;
}
signed main()
{
//freopen(".in","r",stdin);
//freopen(".out","w",stdout);
n = read();
for(int i = 1; i <= n; i++)
{
a = read();
int flag = 0;
if(a == 2){printf("3\n"); continue;}
if(a == 1 || a == 3){printf("2\n"); continue;}
int f = sqrt(double(a)); //分界线
for(int j = 2; j <= f + 1; j++)
if(judge(a, j)) {printf("%lld\n", j); flag = 1; break;}
if(!flag)
{
for(int j = f - 1; j >= 0; j--) //枚举的是b
{
if(a % j == 0)
{
printf("%lld\n", a / j - 1);
break;
}
}
}
}
return 0;
}