P1017 进制转换
先从正进制开始考虑。
例如二进制:
18=1*2^4+0*2^3+0*2^2+1*2^1+0*2^0=0+2(1+2(0+2(0+2(1))))
k=a[n]*2^n+a[n-1]*2^(n-1)+...+a[0]*2^0=a[0]+2(a[1]+2(...+2(a[n])...)...)
短除法将k转换为二进制就是把k除以二,留下商,记录下余数,然后再对商执行此操作,不断重复直到数变为0,再将所有余数倒序输出,根据此式可看出其原理就是第i次除以二时的余数显然就是a[i-1]。
然后考虑负进制。
如负二进制:
k=a[0]-2(a[1]-2(...-2(a[n])...)...)
根据题意,a[0],a[1],...,a[n] >=0
由此可得出将k转换为负二进制的短除法方法:(开始时i=0)
①寻找一个整数p,使得 -2p≤k 且-2p 在可能的范围内最大,记录下k-(-2p),即为a[i]
②如果p为0则进入下一步,如果不为0则p->k(将p赋值给k),i++,然后回到第①步
③得出答案:n=i,k=a[n]*(-2)^n+a[n-1]*(-2)^(n-1)+...+a[0]*(-2)^0
(其它进制可由此类比)
另外,还有一点需要注意:得到p可以用取模运算,但是pascal、c++等对负数的取模有点儿不一样,需要注意一下。
const sz:array[0..20] of char=('0','1','2','3','4','5','6','7','8','9','A','B','C','D','E','F','G','H','I','J','K');
var a:array[1..1000] of integer;
i,i1,j,n1,n,r,t1,t2:longint;
begin
readln(n1,r);
n:=n1;
while n<>0 do
begin
inc(i1);
t1:=n div r;
t2:=n mod r;
if t2<0 then inc(t1);
a[i1]:=n-r*t1;
n:=t1;
end;
write(n1,'=');
for i:=i1 downto 1 do
write(sz[a[i]]);
write('(base',r,')');
end.