题解:P2425 小红帽的回文数
P2425 题解
题面
题意
给定 t 个数,对于每个数 n,求一个最小的 p,使得 n 在 p 进制下是回文数。
思路
首先看到这道题就想要暴力,但是发现 n⩽1010,一看 O(nt) 的暴力复杂度是不行的。
接下来考虑如何优化,注意到一个性质,当 √n⩽p⩽n 时,n 在 p 进制下只有两位数,这个可以很好判,而 p<√n 时直接暴力,暴力到了就直接下一个数,我们来推一下只有两位数的情况。
设 p 满足题意,则有如下式子。
∃i,i<p,i×p+i=n
转化一下。
p=ni−1
由于 p 一定要是整数,所以只要从 √n 开始(因为要满足 √n⩽p⩽n)从大到小(这样枚举到第一个满足条件的它所对应的 p 一定是最小的)枚举 i,满足 nmodi=0 且 p>i。
如果一个都没有枚举到,那么就输出 n+1,因为 n+1 进制下的 n 一定是 n,回文。
于是就可以快乐地对了这道题啦~
实现细节
- 注意从大到小枚举 i。
- 注意有没有 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;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现