Same binary weight
-
描述
-
The binary weight of a positive integer is the number of 1's in its binary representation.for example,the decmial number 1 has a binary weight of 1,and the decimal number 1717 (which is 11010110101 in binary) has a binary weight of 7.Give a positive integer N,return the smallest integer greater than N that has the same binary weight as N.N will be between 1 and 1000000000,inclusive,the result is guaranteed to fit in a signed 32-bit interget.
-
输入
-
The input has multicases and each case contains a integer N.
输出
- For each case,output the smallest integer greater than N that has the same binary weight as N. 样例输入
-
1717 4 7 12 555555
样例输出
-
1718 8 11 17 555557
-
全排列:next_permutation的内部原理
-
首先:如果一个排列为A,下一个排列为A_NEXT,那么A_NEXT一定与A有尽可能长的公共前缀。
看具体例子,一个排列为124653,如何找到它的下一个排列,因为下一个排列一定与124653有尽可能长的前缀,所以,脑洞大开一下,从后面往前看这个序列,如果后面的若干个数字有下一个排列,问题就得到了解决。
第一步:找最后面1个数字的下一个全排列。
124653,显然最后1个数字3不具有下一个全排列。
第二步:找最后面2个数字的下一个全排列。
124653,显然最后2个数字53不具有下一个全排列。
第三步:找最后面3个数字的下一个全排列。
124653,显然最后3个数字653不具有下一个全排列。
第四步:找最后面4个数字的下一个全排列。
124653,我们发现显然最后4个数字4653具有下一个全排列。因为它不是递减的,例如6453,5643这些排列都在4653的后面。
我们总结上面的操作,并总结出重复上面操作的两种终止情况:
1:从后向前比较相邻的两个元素,直到前一个元素小于后一个元素,停止
2:如果已经没有了前一个元素,则说明这个排列是递减的,所以这个排列是没有下一个排列的。
124653这个排列终止情况是上面介绍的第一种,从后向前比较相邻的2个元素,遇到4<6的情况停止。
并且我们可以知道:
1:124653和它的下一个排列的公共前缀为12(因为4653存在下一个排列,所以前面的数字12保持不变)
2:4后面的元素是递减的(上面介绍的终止条件是前一个元素小于后一个元素,这里是4<6)
现在,我们开始考虑如何找到4653的下个排列,首先明确4后面的几个数字中至少有一个大于4.
4肯定要和653这3个数字中大于4的数字中(6,5)的某一个进行交换。这里就是4要和6,5中的某一个交换,很明显要和5交换,如果找到这样的元素呢,因为我们知道4后面的元素是递减的,所以在653中从后面往前查找,找到第一个大于4的数字,这就是需要和4进行交换的数字。这里我们找到了5,交换之后得到的临时序列为5643.,交换后得到的643也是一个递减序列。
所以得到的4653的下一个临时序列为5643,但是既然前面数字变大了(4653--->5643),后面的自然要变为升序才行,变换5643得到5346.
所以124653的下一个序列为125643.
-
思路和next_permutation内部原理一样,可以找最小的
-
从右往左找到第一个后面有1的0,交换0和靠左的1的位置,然后再所有靠右的1移到最右端。 例如:12的二进制为01100,交换最左边的0和1,得10100,再把右边的1移到最右,得10001。
-
#include<stdio.h> #include<string.h> #include <algorithm> using namespace std; int h,p,n; int b[100000],c[100000]; void we(int a)//找这个数二进制 { h=0; p=0; memset(b,0,sizeof(b)); memset(c,0,sizeof(c)); while(a) { b[p++]=a%2; a=a/2; } b[p++]=0; for(int i=p-1; i>=0; i--) { c[h++]=b[i]; } } int qp(int n,int k)//快速幂 { int ret = 1; while(k) { if(k&1) ret = (ret*n); k = k>>1; n = n*n; } return ret; } int main() { while(scanf("%d",&n)!=-1) { we(n); int sum=0; int l=0; next_permutation(c,c+h);//对c进行排列一次,找出最小的那个二进制数组 for(int i=h-1; i>=0; i--)//把二进制转换为数字 { sum+=c[i]*qp(2,l); l++; } printf("%d\n",sum); } }
-
The input has multicases and each case contains a integer N.