数字检测 题解
题目id:20317
题目描述
作为一个学渣的鱼大大在学习了进制数之后,经常会写错进制数,导致他在做题的时候经常出现,写到了最后发现数字是错的情况,非常浪费时间。所以他迫切地想要一位大聪明随时随刻能帮他检测一下他写的\(n\)进制数到底是不是对的。现在鱼大大给出了一个\(n\)进制的数\(m\),问此进制数是否合法。
注:大于\(10\)进制的数,超过9的数字分别用大写字母A ~ Z
表示
解题思路
本题十分简单,就是一道转进制的模板题再加上一些判断,当然还有小小(dà dà)的坑,会使你丢掉\(40\)分呢。
由于进制可能大于\(10\),于是我们需要建立一个用于存放所有进制所有可能出现的数(或字母)的表,最大可以表示到Z
,现建表如下:
string jz="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";
本蒟蒻第一次提交\(80pts\)就是表没建对\(QwQ\),只考虑了十六进制A ~ F
,第二次就\(\textcolor[RGB]{82,196,26}{Accepted}\)了,可恶o(≧口≦)o
假设输入的为\(n\)进制,那么在该进制中最大可出现的字符就是\(jz_{n-1}\),遍历整个数即可,若某个数的\(ASCLL\)码比\(jz_{n-1}\)大,就输出当前下标加\(1(\)因为字符串下标从\(0\)开始\()\)和当前字符,输出后直接结束程序。
for(int i=0;i<s.length();++i)
if(s[i]>jz[n-1])
{
cout<<i+1<<' '<<s[i]<<'\n';
flag=1;
}
if(flag)exit(0);
这里,就要说那个会使你丢掉\(40\)分的很坑的点了:
题目里说:保证输入数据只包含数字和字母,但它没说一定是大写字母,如果只考虑大写就只有\(60pts\),还好我发现了。
接下来转\(10\)进制大家都会吧,一边除以\(10\)一边模\(10\),模板如下:
while(sum)
{
ten[++t]=sum%10;
sum/=10;
}
再加一个考虑字母即可:
for(int i=s.length()-1;i>=0;--i)
{
if(s[i]>='0'&&s[i]<='9')
sum+=cnt*(s[i]-48);
else
sum+=cnt*(s[i]-55);
cnt*=n;
}
while(sum)
{
ten[++t]=sum%10;
sum/=10;
}
其中sum+=cnt*(s[i]-55);
中\(55\)是\(-65+10\)的化简,先转数字在加上大于十进制的\(10\)。
AC Code
#include<bits/stdc++.h>
#define N 1000007
#define INF 1e18
#define ll long long
#define max(a,b) ((a)>(b)?(a):(b))
#define min(a,b) ((a)<(b)?(a):(b))
#define IOS ios::sync_with_stdio(0),cin.tie(nullptr),cout.tie(nullptr)
using namespace std;
string jz="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ",s;
int n,sum,cnt=1,ten[114514],t;
bool flag;
int main()
{
IOS;
cin>>n>>s;
for(int i=0;i<s.length();++i)
if(s[i]>jz[n-1])
{
cout<<i+1<<' '<<s[i]<<'\n';
flag=1;
}
if(flag)exit(0);
for(int i=s.length()-1;i>=0;--i)
{
if(s[i]>='0'&&s[i]<='9')
sum+=cnt*(s[i]-48);
else
sum+=cnt*(s[i]-55);
cnt*=n;
}
while(sum)
{
ten[++t]=sum%10;
sum/=10;
}
for(int i=t;i;--i)
cout<<ten[i];
return 0;
}