hiho209 Powers of Two
描述
Given a positive integer N, it is possible to represent N as the sum of several positive or negative powers of 2 (± 2k for some k). For example 7 can be represented as 22 + 21 + 20 and 23 + (-20).
Your task is to find the representation which contains the minimum powers of 2.
输入
One positive integer N.
For 80% of the data: 1 <= N <= 100000
For 100% of the data: 1 <= N <= 2000000000
输出
The minimum number of powers of 2.
7样例输出
2
题意分析:
给你一个数字n,比如7,7可以描述为2^2+2^1+2^0我们是知道的,但我们现在也可以将之描述为2^3-2^1,
前一种方法用了3个描述7这个数字,而后一种只用了两个,我们就是要找到能描述出n的最少数字个数.
思路:
通过n的二进制码动手,我们可以发觉之所以我们能用更少的2幂次数来描述一个数是因为我们普遍的采用了一种方法:
比如数字1265的二进制如下
1 0 0 1 1 1 1 0 0 0 1
1 0 1 0 0 0 -1 0 0 0 1
像出现上图红色部分这种连续的1时,我们可以将红色部分转为下方的形式(-1即表示减去这个位置的位权),这样就完成了如下转化: 2^11+2^8+2^7+2^6+2^5+2^0 -> 2^11+2^9-2^5+2^0
描述所需数字从6个降低到了4个,这就是核心思维.
实现时的小细节:
设计为仅位移到0的位置时进行判断是否执行收缩(收缩指的就是上面所介绍的那种缩短方法),为1时只是记录1的数目加1;因为这个设计由0触发,故而对应7的二进制,我们应该理解为0111而不是111;最后的0用于触发收尾.
ac代码:
#include <stdio.h>
int mycal(int n){
int ans,k;
ans=k=0;
do{
k+=n&1; //记录当前位置前方连续的1的数目
n>>=1;
if(!(n&1)){
if(n&2){
if(k>1){//执行收缩
ans+=1;
k=1;
}
else if(k==1){ //不收缩
ans+=1;
k=0;
}
}else{
if(k>1){//执行收缩
ans+=2;
k=0;
}
else if(k==1){ //不收缩
ans+=1;
k=0;
}
}
}
}while(n);
return ans;
}
int main(){
int n;
scanf("%d",&n);
printf("%d",mycal(n));
return 0;
}