NKOJ-Unknow 迴文數

迴文數
問題描述

    給你一個數 N, 求出最小的 B(B>=2) , 使得 N 在 B 進制下爲迴文數。

輸入

    第一行 1 個整數 T, 表示數據組數。 接下來 T 行, 每行一個整數 N。

輸出

    輸出 T 行, 每行對應一個答案 B。

樣例
樣例輸入1

3
1
4
21

樣例輸入2

3
5
6
7

樣例輸入3

3
345
5462
345332

樣例輸出1

2
3
2

樣例輸出2

2
5
2

樣例輸出3

22
52
114

數據範圍

30%的數據 T<=10, N<=10^4。
100%的數據 T<=1,000, N<=10^10

懵逼.jpg

題解

讀題

舉個例子
3->二進制11
4->三進制11
1400->39進制 35 35
             ^  ^  每一個^表示一位

舉完這些個例子你們差不多就知道題意了
轉進制之後,從最高位往下讀和從最低位往上讀的結果都是一樣的

討論

這道題目沒有任何規律
就是暴力枚舉

但是我們絕對不滿足於暴力地暴力枚舉!
就算是暴力枚舉我們也要有可以裝逼的地方!

於是,在只過了兩個點之後我痛定思痛,看了題解,抄到了以下結論

枚舉進制我們分爲2位,和比兩位多的位數

對於數字N=B*B轉K進制後只有兩位AA的情況
有以下結論
    A<K
    A*K^1+A*K^0=A*(K+1)=N
    所以A*(K+1)=B*B=N

    ①
        B=B
        A<K+1
        ==>A<B

    ②
        K=N/A-1>B

所以對於進制K高於B位的,我們可以通過枚舉A得到

所以對於轉進制後只有兩位的數字,求解方法如下

for(int A=sqrt(N);A;A--)
    if(N%A==0)return N/A-1;

那麼以上結論適用於進制大於sqrt(N)的
那麼對於K<=sqrt(B)的,只需要 枚舉+判斷 即可

例如對於N是否可以轉成K進制的迴文數,方法如下

int use[100];
bool check(int N,int K)
{
    pos=0;
    while(N)use[pos++]=N%K,N/=K;//轉進制
    for(int i=0;i<=pos>>1;i++)
        if(use[i]!=use[pos-1-i])return 0;//如果從做數起第i位和從右數起第i位不同,那麼就不行
    return 1;//否則就可以
}

注意

①對於任何N>1,轉成N-1進制一定可以,且轉換結果一定爲11(1*(N-1)^1+1*(N-1)^0=N)
②無論如何請從K=2枚舉

附上對拍代碼

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
using namespace std;

inline long long input()
{
    char c=getchar();long long o;
    while(c>57||c<48)c=getchar();
    for(o=0;c>47&&c<58;c=getchar())o=(o<<1)+(o<<3)+c-48;
    return o;
}

long long T,x,res[100];

void GET(long long x)
{
    long long resA=0;
    for(long long i=2;i<=sqrt(x)+1;i++)
    {
        long long a=x,pos=0,flag=1;
        while(a)
            res[pos++]=a%i,a/=i;
        for(long long a=0;a<=pos+1>>1;a++)
            if(res[a]!=res[pos-1-a])flag=0;
        if(x%i==0&&x/i-1>i)resA=x/i-1;
        if(flag){printf("%lld\n",i);return;}
    }
    if(resA){printf("%lld\n",resA);return;}
    printf("%lld\n",x-1);
}

int main()
{
    freopen("number.in","r",stdin);
    freopen("number.out","w",stdout);
    T=input();
    for(long long i=1;i<=T;i++)
    {
        x=input();
        if(x==1)printf("2\n");
        if(x==2)printf("3\n");
        if(x>2)GET(x);
    }
}
發佈了79 篇原創文章 · 獲贊 15 · 訪問量 1萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章