ACM-模拟-找规律 HDU5573二进制应用

原理就是二进制的转换
0001==8-4-2-1(奇数)
01011==(16-8)+(4-2)+1 (奇数)(首位不变)
01010==((16+1)-8)+(4-2)+1(偶数)(首位加一)
对于二进制数 16==32-16==16==64-32-16
所以,我们转换n的二进制,然后判断每一段的开头0和末尾1就好
。。。
我天真的以为这样就行了
。。。
但是还有
1.n可能是负数—–用个标记jud,判断输出+/-就行,正负转换就好
2.对于n为偶数的情况我的模拟判断有些漏洞,比如10100(20)最后的00不符合一段的要求,那么,我们就处理完首位,赖皮的n–,变成奇数就能保证判断了。

#include
#define ll long long
#define mem0(a,b) memset(a,b,sizeof(a))
using namespace std;
bool a[61];
ll pp[61];
inline int cale(ll p){//二进制转换
    mem0(a,false);
    int i=1;
    while(p){
        a[i]=p&1;
        p/=2;
        i++;
    }
    return i-1;
}
void init(){//处理2^k
    pp[0]=1;
    pp[1]=1;
    for(int i=2;i<61;i++){
        pp[i]=pp[i-1]*2;
    }
}
int t,k;
ll n;
bool jud=true;
mapbool>num;
int main(){
    scanf("%d",&t);
    init();
    for(int cas=1;cas<=t;cas++){
        jud=true;//判断正负
        scanf("%I64d %d",&n,&k);
        printf("Case #%d:\n",cas);
        num.clear();
        if(n<0){
            n*=-1;
            jud=false;
        }
        if(n&1){
            num[pp[k]]=true;
        }
        else {
            num[pp[k]+1]=true;
            n--;//偶变奇
        }
        int temp=cale(n);
        bool jia=a[k];//判断是不是一段的开始
        for(int i=k-1;i>=1;i--){
            if(jia&&!a[i]&&i!=1){//首0
                num[pp[i]]=true;
                jia=false;
            }
            else if(a[i]&&!jia){//尾1
                num[pp[i]]=false;
                jia=true;
            }
            else num[pp[i]]=a[i];
        }
        mapbool>::iterator it=num.begin();
        while(it!=num.end()){
            printf("%I64d ",(*it).first);
            if(jud){//positive
                if((*it).second)printf("+\n");
                else printf("-\n");
            }
            else {//negative
                if((*it).second)printf("-\n");
                else printf("+\n");
            }
            it++;
        }
    }
    return 0;
}

你可能感兴趣的:(算法题解)