小红帽的回文数

小红帽的回文数

题解:

对于一个数\(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;
}
posted @ 2021-10-05 06:35  _程门立雪  阅读(39)  评论(0编辑  收藏  举报