题解:UVA12050 Palindrome Numbers
双倍经验:ABC363D。
思路
打表
对应的答案 | |
---|---|
不难发现,每一次答案多一位,
然后我们就可以依此写出来一个打表程序。
观察最后一组样例发现有
#include<bits/stdc++.h>
using namespace std;
int main(){
cout<<"1,";
for(int i=2;i<=35;i++){
if(i%2==1){
cout<<"2";
for(int j=1;j<=i/2;j++)cout<<'0';
cout<<',';
}
else {
cout<<"11";
for(int j=1;j<i/2;j++)cout<<'0';
cout<<',';
}
if(i%4==0)cout<<endl;
}
return 0;
}
注意到一位数包括
打表出来的数组是:
long long wei[45]= {0,1,11,20,110,
200,1100,2000,11000,
20000,110000,200000,1100000,
2000000,11000000,20000000,110000000,
200000000,1100000000,2000000000,11000000000,
20000000000,110000000000,200000000000,1100000000000,
2000000000000,11000000000000,20000000000000,110000000000000,
200000000000000,1100000000000000,2000000000000000,11000000000000000,
20000000000000000,110000000000000000,200000000000000000,1000000000000000001};
我们在这个序列中找到第一个大于等于
然后我们对奇数位和偶数位分开处理。
偶数位
不难发现答案为偶数位的
所以答案为偶数位的
所以我们把
void dfs2(int now) {
if(now>q/2+1)return;
cout<<n10[now];
dfs2(now+1);
cout<<n10[now];
}
奇数位
奇数位的处理相对麻烦一点。
首先先看答案的最高位(最低位),其实就是
然后除掉
void dfs1(int now) {
if(n10[1]==1&&n10[2]==0&&now==1) {//因为对最高位是 1 的情况过于麻烦,我特判了一下
bool f=1;
for(int i=3; i<=cnt; i++) {
if(n10[i]!=0)f=0;
}
if(f) {
cout<<9;
for(int i=2; i<q; i++)cout<<0;
cout<<9;
return;
}
else{
cout<<9;
q++;
dfs1(3);
cout<<9;
return;
}
}
int g=0;
if(now==q/2+1) {
cout<<n10[now];
return;
}
if(now==1) {
cout<<n10[now]-1;
} else cout<<n10[now];
dfs1(now+g+1);
if(now==1) {
cout<<n10[now]-1;
} else cout<<n10[now];
}
完整代码
#include<bits/stdc++.h>
using namespace std;
long long wei[45]= {0,1,11,20,110,
200,1100,2000,11000,
20000,110000,200000,1100000,
2000000,11000000,20000000,110000000,
200000000,1100000000,2000000000,11000000000,
20000000000,110000000000,200000000000,1100000000000,
2000000000000,11000000000000,20000000000000,110000000000000,
200000000000000,1100000000000000,2000000000000000,11000000000000000,
20000000000000000,110000000000000000,200000000000000000,1000000000000000001
};
//设置最后一个数的意义:防止对于极大的数据找不到要求的位数
long long n;
int flag,n10[25],cnt,q;
void dfs1(int now) {
if(n10[1]==1&&n10[2]==0&&now==1) {
bool f=1;
for(int i=3; i<=cnt; i++) {
if(n10[i]!=0)f=0;
}
if(f) {
cout<<9;
for(int i=2; i<q; i++)cout<<0;
cout<<9;
return;
}
else{
cout<<9;
q++;
dfs1(3);
cout<<9;
return;
}
}
int g=0;
if(now==q/2+1) {
cout<<n10[now];
return;
}
if(now==1) {
cout<<n10[now]-1;
} else cout<<n10[now];
dfs1(now+g+1);
if(now==1) {
cout<<n10[now]-1;
} else cout<<n10[now];
}
void dfs2(int now) {
if(now>q/2+1)return;
cout<<n10[now];
dfs2(now+1);
cout<<n10[now];
}
int ans[15]= {0,0,1,2,3,4,5,6,7,8,9};
int main() {
cin>>n;
if(n<=10) {
cout<<ans[n];
return 0;
}
for(int i=1; i<=36; i++) {
if(wei[i]>n) {
//问题:当 n 取极大值时,如果只是判断 35 位,可能找不到 q 的值
flag=(i-1)%2;
q=i-1;
break;
}
}
while(n) {
n10[++cnt]=n%10;
n/=10;
}
for(int i=1; i<=cnt/2; i++) {
swap(n10[i],n10[cnt-i+1]);
}
if(flag)dfs1(1);
else dfs2(2);
return 0;
}
为什么可以用递归实现?
因为不难发现一个奇位回文数都是在之前产生的一个奇位回文数两边加上一个相同的数,偶位回文数同理。
这样,我们可以递归把
分类:
题解
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】