题解:P2425 小红帽的回文数

P2425 题解

题面

原题传送门

题意

给定 t 个数,对于每个数 n,求一个最小的 p,使得 np 进制下是回文数。

思路

首先看到这道题就想要暴力,但是发现 n1010,一看 O(nt) 的暴力复杂度是不行的。

接下来考虑如何优化,注意到一个性质,当 npn 时,np 进制下只有两位数,这个可以很好判,而 p<n 时直接暴力,暴力到了就直接下一个数,我们来推一下只有两位数的情况。

p 满足题意,则有如下式子。

i,i<p,i×p+i=n

转化一下。

p=ni1

由于 p 一定要是整数,所以只要从 n 开始(因为要满足 npn)从大到小(这样枚举到第一个满足条件的它所对应的 p 一定是最小的)枚举 i,满足 nmodi=0p>i

如果一个都没有枚举到,那么就输出 n+1,因为 n+1 进制下的 n 一定是 n,回文。

于是就可以快乐地对了这道题啦~

实现细节

  1. 注意从大到小枚举 i
  2. 注意有没有 i 的情况为 n+1

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
using namespace std;
const int MN=64;
ll n,t[MN],l;
void write(ll n){if(n<0){putchar('-');write(-n);return;}if(n>9)write(n/10);putchar(n%10+'0');}
ll read(){ll 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<<1)+(x<<3)+(ch^48);ch=getchar();}return x*f;}
bool check(ll x, ll n){//判回文。
    l=0;//长度要初始化。
    while(n){
        t[++l]=n%x;//把每个数统计出来。
        n/=x;
    }
    for(int i=1; i<=l/2; i++) if(t[i]!=t[l-i+1]) return false;
    return true;
}
void solve(){
    n=read();
    for(int i=2; i<=sqrt(n); i++) if(check(i,n)){write(i);putchar('\n');return;}//暴力判断小于等于根号n。
    for(int i=sqrt(n); i>=1; i--) if(n%i==0&&n/i-1>i&&n/i-1>sqrt(n)){write(n/i-1);putchar('\n');return;}//只要加这一句就AC了!
    //枚举i*p+i=n的i,注意有if中的限制,由于要最小的p,那么就从大到小来枚举i。
    write(n+1);putchar('\n');//前面的都不行,n+1进制的n一定是n,回文。
}
int main(){
    ll T=read();while(T--)solve();
    return 0;
}
posted @   naroto2022  阅读(7)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
花开如火,也如寂寞。