//356K 0MS G++
#include <cstdio>
#include <cstring>
const int MAX = 40;
long long rankWeight[MAX];
void init() {
long long begin = 2;
for (int i = 0; i < MAX; i++) {
rankWeight[i] = begin - 1;
// printf("%lld ", rankWeight[i]);
begin <<= 1;
}
// printf("\n");
}
http://write.blog.csdn.net/postedit/39203945
int binarySearch(int val) {
// printf("binarySearch %d\n", val);
int begin = 0;
int end = MAX-1;
while(1) {
if (begin > end) {
break;
}
int mid = (begin + end)/2;
if (rankWeight[mid] == val) {
// printf("%d found!\n", val);
return mid;
} else if (rankWeight[mid] > val) {
end = mid - 1;
} else if (rankWeight[mid] < val) {
begin = mid + 1;
}
}
// printf("%d not found!\n", val);
return -1;
}
int res[30];
int resPos;
int caseNum;
long long getMaxLessEqualThan(int demicalVal, int & weightRank) {
long long res = 0;
for (int i = 0; i <MAX; i++) {
if (rankWeight[i] > demicalVal) {
res = rankWeight[i-1];
weightRank = i-1;
break;
}
}
return res;
}
void getSkewBinary(int demicalVal) {
if (demicalVal == 0) {
printf("0 []\n");
return;
}
int curDemicalVal = demicalVal;
while(1) {
int CurValWeightRank = binarySearch(curDemicalVal);
if (CurValWeightRank >= 0) {
res[resPos++] = CurValWeightRank;
break;
} else {
if (curDemicalVal%2==0) {
int halfVal = curDemicalVal/2;
if (halfVal%2 == 1) {
int HalfCurValWeightRank = binarySearch(halfVal);
if (HalfCurValWeightRank >= 0) {
res[resPos++] = HalfCurValWeightRank;
res[resPos++] = HalfCurValWeightRank;
break;
}
}
}
int weightRank = -1;
int MaxLessEqual = getMaxLessEqualThan(curDemicalVal, weightRank);
if (MaxLessEqual == 0 || weightRank == -1) {
break;
} else {
res[resPos++] = weightRank;
curDemicalVal -= MaxLessEqual;
}
}
}
long long checkVal = 0;
printf("%d [", demicalVal);
for (int i = resPos-1; i >= 0; i--) {
checkVal += rankWeight[res[i]];
if (i >0) {
printf("%d,", res[i]);
} else if (i == 0) {
printf("%d", res[i]);
}
}
printf("]\n");
// printf("%lld\n", checkVal);
}
int main() {
init();
scanf("%d", &caseNum);
for (int i = 1; i <= caseNum; i++) {
int demicalVal;
memset(res, 0xff, sizeof(res));
resPos = 0;
scanf("%d", &demicalVal);
getSkewBinary(demicalVal);
}
}
题意比较难懂,不过懂了以后也算个小水题吧。
题意是给了一堆的进制权,i从0开始,依次是2的i+1次方减一(1, 3, 7 , 15),对于某个十进制数,都要用这些进制位将其表示出来,依照从进制权值从小到大的顺序:
另外有一点就是不能有两个相同的进制权位相邻,除非是最开始的两位。
比如:
对于 15, 【0 3 3】 也等于 15(0的权值 1 + 3的权值7 + 3的权值7 = 15),但是因为3 3不是最后两位,所以不行,
同时,因为权值都是奇数,所以不存在一个偶数有两种表示的方式 (比如 [k,k] 或者 [m])
这样策略就简单了:
对于一个十进制数S ,先看看其是否就是一个权值,如果是,那么直接将权值对应的位输出即可,
否则,再看其是是否为偶数,如果是偶数,在看S/2是否是一个权值V,如果是,那么直接输出[V,V],
否则,就找到最大的小于S的权值,将其对应位加入到结果数组中,并且,S 减去此权值,继续操作,
知道S == 0,整个过程结束.