P1017 进制转换
题目链接
题目描述
我们可以用这样的方式来表示一个十进制数: 将每个阿拉伯数字乘以一个以该数字所处位置的(值减1)为指数,以10为底数的幂之和的形式。例如:123可表示为 1 ∗ 1 0 2 + 2 ∗ 1 0 1 + 3 ∗ 1 0 0 1*10^2+2*10^1+3*10^0 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无关。如果作为基数的数绝对值超过1010,则为了表示这些数码,通常使用英文字母来表示那些大于9的数码。例如对16进制数来说,用A表示10,用B表示11,用C表示12,用D表示13,用E表示14,用F表示15。
在负进制数中是用 -R 作为基数,例如-15(十进制)相当于110001110001(-2进制),并且它可以被表示为22的幂级数的和数:
110001 = 1 ∗ ( − 2 ) 5 + 1 ∗ ( − 2 ) 4 + 0 ∗ ( − 2 ) 3 + 0 ∗ ( − 2 ) 2 + 0 ∗ ( − 2 ) 1 + 1 ∗ ( − 2 ) 0 110001=1*(-2)^5+1*(-2)^4+0*(-2)^3+0*(-2)^2+0*(-2)^1 +1*(-2)^0 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
输出样例 #1:
30000=11011010101110000(base-2)
输入样例 #2:
-20000 -2
输出样例 #2:
-20000=1111011000100000(base-2)
输入样例 #3:
28800 -16
输出样例 #3:
28800=19180(base-16)
输入样例 #4:
-25000 -16
输出样例 #4:
-25000=7FB8(base-16)
说明
NOIp2000提高组第一题
题解
这题让我们深究一下进制转换背后的秘密。
任何一个整数数在 R 进制下表现为 a n ∗ R n + a n − 1 ∗ R n − 1 + . . . + a [ 1 ] ∗ R 1 + a [ 0 ] ∗ R 0 a_n*R^n+a_{n-1}*R^{n-1}+...+a[1]*R^1+a[0]*R^0 an∗Rn+an−1∗Rn−1+...+a[1]∗R1+a[0]∗R0
我们的任务其实就是求出每个 a i a_i ai。
根据题目描述中的例子(小一点,输入样例2万3万的玩儿不起)
− 1 5 ( 10 ) = 11000 1 ( − 2 ) = 1 ∗ ( − 2 ) 5 + 1 ∗ ( − 2 ) 4 + 0 ∗ ( − 2 ) 3 + 0 ∗ ( − 2 ) 2 + 0 ∗ ( − 2 ) 1 + 1 ∗ ( − 2 ) 0 -15_{(10)}=110001_{(-2)}=1*(-2)^5+1*(-2)^4+0*(-2)^3+0*(-2)^2+0*(-2)^1 +1*(-2)^0 −15(10)=110001(−2)=1∗(−2)5+1∗(−2)4+0∗(−2)3+0∗(−2)2+0∗(−2)1+1∗(−2)0
− 1 5 ( 10 ) = 11000 1 ( − 2 ) = a 5 ∗ ( − 2 ) 5 + a 4 ∗ ( − 2 ) 4 + a 3 ∗ ( − 2 ) 3 + a 2 ∗ ( − 2 ) 2 + a 1 ∗ ( − 2 ) 1 + a 0 ∗ ( − 2 ) 0 -15_{(10)}=110001_{(-2)}=a_5*(-2)^5+a_4*(-2)^4+a_3*(-2)^3+a_2*(-2)^2+a_1*(-2)^1 +a_0*(-2)^0 −15(10)=110001(−2)=a5∗(−2)5+a4∗(−2)4+a3∗(−2)3+a2∗(−2)2+a1∗(−2)1+a0∗(−2)0
显然, − 15 m o d − 2 -15\ \ mod\ -2 −15 mod −2 即为我们想要的 a 0 a_0 a0。
接下来,由于 a 0 a_0 a0 已知,代入后移项得:
− 15 − 1 ∗ ( − 2 ) 0 = a 5 ∗ ( − 2 ) 5 + a 4 ∗ ( − 2 ) 4 + a 3 ∗ ( − 2 ) 3 + a 2 ∗ ( − 2 ) 2 + a 1 ∗ ( − 2 ) 1 -15-1*(-2)^0=a_5*(-2)^5+a_4*(-2)^4+a_3*(-2)^3+a_2*(-2)^2+a_1*(-2)^1 −15−1∗(−2)0=a5∗(−2)5+a4∗(−2)4+a3∗(−2)3+a2∗(−2)2+a1∗(−2)1
− 16 = a 5 ∗ ( − 2 ) 5 + a 4 ∗ ( − 2 ) 4 + a 3 ∗ ( − 2 ) 3 + a 2 ∗ ( − 2 ) 2 + a 1 ∗ ( − 2 ) 1 -16=a_5*(-2)^5+a_4*(-2)^4+a_3*(-2)^3+a_2*(-2)^2+a_1*(-2)^1 −16=a5∗(−2)5+a4∗(−2)4+a3∗(−2)3+a2∗(−2)2+a1∗(−2)1
两边同时约去 -2
− 8 = a 5 ∗ ( − 2 ) 4 + a 4 ∗ ( − 2 ) 3 + a 3 ∗ ( − 2 ) 2 + a 2 ∗ ( − 2 ) 1 + a 1 ∗ ( − 2 ) 0 -8=a_5*(-2)^4+a_4*(-2)^3+a_3*(-2)^2+a_2*(-2)^1+a_1*(-2)^0 −8=a5∗(−2)4+a4∗(−2)3+a3∗(−2)2+a2∗(−2)1+a1∗(−2)0
这个式子又回到了刚才的形式。我们可以继续操作,直到求出 a 5 a_5 a5。
代码
#include
#define LL long long
LL n,R;
int len,yu;
char a[10000];
int main()
{
scanf("%lld%lld",&n,&R);printf("%lld=",n);
for (len=0;n!=0;++len)
{
yu=(n%R-R)%R;
if (yu<10) a[len]=yu+'0';else a[len]=yu+'A'-10;
n-=yu*e;
n/=R;
}
for (--len;len>=0;--len) printf("%c",a[len]);
printf("(base%d)",R);
return 0;
}