将D转化为2进制保存一个数组里,从低位开始找第一个“0”;
首先把第一个满足题意的“0”后面全部赋值“0”;然后再从地位开始补“1";补的“1的个数为 S1-(满足题意的0前面1的个数);
注意:虽然D<2^31-1,但是数组要开32位,因为比如可能有1后面30个0或者30个1的情况,就会进到32位。
代码如下
#include <stdio.h> #include <iostream> #include <string.h> #include <algorithm> #include <math.h> using namespace std; long long d,s1,s2; int t,i,a[33]; int go(int ii) //求 1 的个数的函数 { int cnt=0; for(int k=1;k<=32;k++) { if(ii%2==1) { a[k]=1; cnt++; } else a[k]=0; ii/=2; } return cnt; } int main() { scanf("%d",&t); long long ans; int k,m,cnt1,cnt2; for(int cas=1;cas<=t;cas++) { scanf("%lld%lld%lld",&d,&s1,&s2); ans=0; cnt1=0; memset(a,0,sizeof(0)); cnt2=go(d); // cnt2 = 给的D的 1 的个数 cnt1=0; //第一个 满足题意的 0 后面的1的个数 for(k=1;k<=32;k++) { if(a[k]==0) { if(cnt2==s2) //如果cnt2 ==s2 判断当前0后面的1的个数是否为0 { if(cnt1>0) { a[k]=1; m=k; //记录第一个满足题意的0的位置 break; } } else { m=k; a[k]=1; //将第一个满足的0改为1 break; } } else cnt1++; } for(i=m-1;i>0;i--) //将第一个满足的0后面 位全部置0 { a[i]=0; } for(i=1;i<s1-(cnt2-cnt1);i++) //从低位开始补1, cnt2-cnt1 = 第一个满足0前面1的个数; a[i]=1; for(i=32;i>0;i--) ans=ans*2+a[i]; printf("Case #%d: %lld\n",cas,ans); } return 0; }