题目背景
NOIP2000提高组 T1
洛谷1017
题目描述
我们可以用这样的方式来表示一个十进制数:将每个阿拉伯数字乘以一个以该数字所处位置的(值减 1)为指数,以 10 为底数的幂之和的形式。例如,123 可表示为
1∗102+2∗101+3∗100
这样的形式。
与之相似的,对二进制数来说,也可表示成每个二进制数码乘以一个以该数字所处位置的(值-1)为指数,以 2 为底数的幂之和的形式。
一般说来,任何一个正整数 R 或一个负整数 -R 都可以被选来作为一个数制系统的基数。如果是以 R 或 -R 为基数,则需要用到的数码为 0,1,…,R-1。例如,当 R=7 时,所需用到的数码是 0,1,2, 3,4,5 和 6,这与其是 R 或 -R 无关。如果作为基数的数绝对值超过 10,则为了表示这些数码,通常使用英文字母来表示那些大于 9 的数码。例如对 16 进制数来说,用 A 表示 10,用 B 表示 11,用 C 表示 12,用 D 表示 13,用 E 表示 14,用 F 表示 15。 在负进制数中是用 -R 作为基数,例如 -15(+进制)相当于 110001(-2进制),并且它可以被表示为 2 的幂级数的和数:
110001=1∗(−2)5+1∗(−2)4+0∗(−2)3+0∗(−2)2+0∗(−2)1+1∗(−2)0
问题求解: 设计一个程序,读入一个十进制数的基数和一个负进制数的基数,并将此十进制数转换为此负进制下的数:-R∈{-2,-3,-4,…,-20}
输入格式
输入只有一行,是两个整数。
第一个是十进制数 N(-32768<=N<=32767), 第二个是负进制数的基数 -R。
输出格式
输出此负进制数,若此基数超过 10,则参照 16 进制的方式处理。
样例数据1
输入
30000 -2
输出
11011010101110000
样例数据2
输入
-20000 -2
输出
1111011000100000
样例数据3
输入
28800 -16
输出
19180
样例数据4
输入
-25000 -16
输出
7FB8
注:洛谷输出有所不同。
分析:正如题目,这是一道进制转换题。不要看到负数就被吓到,其实进制转换的通法就是不断除以进制数存下余数最后逆向输出,只是这道题无法保证余数是正数,我们需要特判,如果<0就把除法答案+1,余数再减一个进制数(因为进制数是负数,所以相当于加上了一个正数),如果还不理解,就试一试题目描述中-15和-2的例子吧:
so easy!
代码
根据洛谷的输出写的代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<cctype>
#include<iomanip>
#include<queue>
#include<set>
using namespace std;
int getint()
{
int sum=0,f=1;
char ch;
for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar());
if(ch=='-')
{
f=-1;
ch=getchar();
}
for(;isdigit(ch);ch=getchar())
sum=(sum<<3)+(sum<<1)+ch-48;
return sum*f;
}
int n,nn,r,rr,cnt;
int a[100];
int main()
{
freopen("change.in","r",stdin);
freopen("change.out","w",stdout);
n=getint(),r=getint();
nn=n,rr=r;
while(n)
{
a[++cnt]=n%r;
if(a[cnt]<0)//特判
{
a[cnt]-=r;
n=n/r+1;
}
else
n=n/r;
}
printf("%d=",nn);
for(int i=cnt;i>=1;--i)
{
if(a[i]>=10)
printf("%c",'A'+a[i]-10);
else
cout<<a[i];
}
printf("(base%d)",rr);
return 0;
}
本题结。