1570: Palindromic Numbers
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 102 Solved: 7
[ Submit][ Status][ Web Board]
Description
Johnny has figured out that there are some numbers which have an interesting property: they are the same when read from left to right, and from right to left. For example, 5115 and 929 are such numbers, while 31 and 125 are not. Johnny calls such numbers palindromic numbers.
After a while, Johnny has realized that his definition of palindromic numbers is not really precise. Whether a number is palindromic or not depends on the base in which the number is written. For example, 21 is not palindromic in base 10 but it is palindromic in base 2 (because 21 = 101012).
Johnny finds it interesting that any number becomes palindromic when it is written in an appropriate base.
Given a number N, write a program to help Johnny compute the smallest base B such that N is palindromic when written in base B.
Input
The first line contains t, the number of test cases (about 1000). Then t test cases follow.
Each test case consists of a number N written in one line (1 <= N <= 1010).
Output
For each given number N, print a line containing the smallest base B such that N is palindromic in base B.
Sample Input
Sample Output
题意:给出一个数N,求一个最小的ans使得N在ans进制下是回文数
首先我直接就爆搜了然后发现超时,然后自己优化,然并卵。。。。还是超时,后面看了大佬的思路。。。发现大佬果然不一样...
如果当前数字为N,那么N可以表示成m*n的形式,也就是N=m*n,那么我们可以发现,当N为(n-1)进制或者(m-1)进制时,N一定为回文数
证明:首先假设m<n,因为题目要求的是最小的进制数,所以肯定取小的数作为上限答案
1.N=m*n=m*(n-1)+m
2.N%(n-1)=(m*(n-1)+m)%(n-1)=m%(n-1)=m
3.N/(n-1)取整=m
4.m%(n-1)=m
5.所以N在(n-1)进制下答案就是mm一定是回文
所以这样就可以得出上限是什么,所以我们只需要判断到sqrt(n)的地方,那么10^10开根号之后也只有10W次的check,每次check速度基本为常数忽略不计,那么时间复杂度为O(Tsqrt(n))
另外我们可以发现,当数字较小时,比如4,用这个判断方法会有问题,但是其实不用想那么多,既然对于10W次的运算都不会有问题,那么我们考虑当n<10000时不开sqrt,爆搜答案是什么即可。
#include<cstdio>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<queue>
using namespace std;
int s[500000];
int play(int m,long long x){
int len=0;
while(x){
s[len]=x%m;
x=x/m;
len++;
}
for(int i=0;i<len/2;i++){
if(s[i]!=s[len-i-1])return 0;
}
return 1;
}
int main()
{
long long n,m,x,y,t;
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
int flag=1,len=sqrt(n);
if(n==1){printf("2\n");continue;}
if(n<10000)len=n;
for(int i=2;i<=len+1;i++){
if(play(i,n)){
printf("%d\n",i);
flag=0;
break;
}
}
if(flag){
len=sqrt(n);
for(long long i=len;i>=1;i--){
if(n%i==0){
printf("%lld\n",n/i-1);
break;
}
}
}
}
return 0;
}