小红帽的回文数
题解:
对于一个数(a[i]) , (a[i] + 1)进制一定能使它成为回文串,(a[i] - 1)进制也一定能使它成为回文串, (例如: (8), 在(9)进制下是(8),在(7)进制下为(11)),所以进制(xleq 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" <<"
"
#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
"); continue;}
if(a == 1 || a == 3){printf("2
"); continue;}
int f = sqrt(double(a)); //分界线
for(int j = 2; j <= f + 1; j++)
if(judge(a, j)) {printf("%lld
", j); flag = 1; break;}
if(!flag)
{
for(int j = f - 1; j >= 0; j--) //枚举的是b
{
if(a % j == 0)
{
printf("%lld
", a / j - 1);
break;
}
}
}
}
return 0;
}