uva 11121 Base -2

数学题,给定一个十进制数转化为-2进制。这个问题可以扩展为转化为任意的负进制,先说-2进制

算法:n mod -2 余数可能为-1,0,1,但是不能出现-1,只能有0,1所以将-1变为1,并且商要加1。然后依此迭代直到商为0为止。

为什么余数要变为1而且能变为1呢,变了之后要怎么做呢?我找了很多博客都没有说原理,只是简单一句话,可能大家都觉得很简单吧,但是我还是想了一段时间才想出来的,所以就写一下原理

我们来看一个10进制转2进制,例子1024

第0次迭代,1024/2=512,1024%2=0 , 试一下把512++变为513,那么逆回去就是1026,多了2,其实就是2^1

第1次迭代,512/2=256,512%2=0,试一下把256++变为257,那么逆回去,就是1028,多了4,其实就是2^2

说到这里应该很清晰了,在第i次迭代后商+1,其实相当于原来的数增加了2^(i+1),这个有什么用呢

n = b0 + b1(-2) + b2(-2)2 + b3(-2)3 + ...

当n为正数的时候,第i次迭代的时候余数为-1的话,那么i一定是奇数(因为余数为正为负只和n的正负有关,而n的正负在除-2的过程中是交替变化的,很容易可以知道当i为奇数的时候,n是负数或0,余数是-1或0)那么对应的位置就应该是 -1*(-2)^i=2^i  ,如果变为1,则是1*(-2)^i=-2^i ,所以变为1后相当于减少了2*2^i=2^(i+1),减少了的要加回来啊,怎么加,就在第i次迭代后的商+1,上面说了,第i次迭代后商+1,相当于逆回去加了2^(i+1),所以以这个商继续迭代下去,最后得到的-2进制数就会等于原来的n

同理,当n为负数的时候,也是一样的分析,就不写了。

 

然后看代码

#include <cstdio>
#include <cstring>
#define N 110
int a[N];
int n;
int main()
{
    int t,T;
    scanf("%d",&T);
    for(int t=1; t<=T; t++)
    {
        scanf("%d",&n);
        int c=-1; a[0]=0;
        while(n)
        {
            a[++c]=n%(-2);
            n=n/(-2);
            if(a[c]==-1)
            { a[c]=1; n++; }
        }
        printf("Case #%d: ",t);
        while(c>0) printf("%d",a[c--]);
        printf("%d",a[0]);
        printf("\n");
    }
    return 0;
}

 

 

按照这个原理我们不难写出转化为任意负进制的代码,先简单文字描述

当n为正数的时候转化为-m进制,同样是当i为奇数的时候,会产生负的余数(或者0)-p,对应的位为(-p)*(-m)^i=p*m^i , 要把-p改为m-p , 那么对应的为就变为了(m-p)*(-m)^i=-(m-p)*m^i , 那么相当于原来减少了m*m^i=m^(i+1) , 减少的要补回来,就是在商那里+1,那么逆回去相当于增加了m^(i+1),刚好不回来,那么转化后的-m进制才是n

同理n为负数的时候也是这么分析的

核心代码

//核心代码

 scanf("%d",&n);
 int c=-1; a[0]=0;
 while(n)
 {
     a[++c]=n%(-m);  //m就是m进制,-m就是负进制
     n=n/(-m);
     if(a[c]<0)
     { a[c]=m+a[c]; n++; }
 }
 printf("Case #%d: ",t);
 while(c>0) printf("%d",a[c--]);
 printf("%d",a[0]);
 printf("\n");

 

posted @ 2012-12-21 18:54  Titanium  阅读(741)  评论(0编辑  收藏  举报