• Gym611B-New Year and Old Property-简单模拟


    【题目大意】给出两个数a,b.求出在[a,b]区间中二进制形式只包含一个0的数字个数。

    【解题思路】对于满足整数域中满足上面要求的数字都是可以按序求出的,例如10,101,110,1011,1101,1110…并且当二进制的长度(不为零的最高位)确定,该长度的满足要求数字个数是确定的。并且可以根据规律求出。

    因此,可以求得≥a且最小的 满足要求的数A(用(l1,z1)表示。L:二进制长度,Z:唯一一个0的位置)同理也有≤b的最大的数B(l2,z2),进而可以根据A和B得出ans。

    代码如下

     1 #include "iostream"
     2 using namespace std;
     3 int Slong(long long s) //求出数字长度
     4 {
     5     int i = 0;
     6     while (s)
     7     {
     8         s = s / 2;
     9         i++;
    10     }
    11     return i;
    12 }
    13 long long getnz(int n, int z)//根据数字长度(二进制)和0的位置==>十进制数字
    14 {
    15     long long i = 1;
    16     long long k = 0;
    17     for (int j = 1 ; j <= n ; j++)
    18     {
    19         if ( j != z )  k += i;
    20         i *= 2;
    21     }
    22     return k;
    23 }
    24 int main()
    25 {
    26     long long a, b;
    27     int n1 = 0, n2 = 0, z1 = 0, z2 = 0;
    28     cin >> a >> b;
    29     int l = Slong(a);
    30     if (a > getnz(l, 1))
    31         // 边界:如果a比该长度下最大的满足要求数字还大,
    32         // A的为(L+1,L)
    33         // 长度比a长1第二高位为0
    34         // (例:10111111111111111……)
    35     {
    36         n1 = l + 1;
    37         z1 = l;
    38     }
    39     else
    40         for ( int i = l - 1 ; i >= 1 ; i-- ) //从小到大枚举该长度下的数字,求A
    41         {
    42             if (getnz(l, i) >= a)
    43             {
    44                 n1 = l;
    45                 z1 = i;
    46                 break;
    47             }
    48         }
    49     l = Slong(b);
    50     if (b < getnz(l, l - 1))
    51         // 边界:如果b比该长度下最小的满足要求数字还小,
    52         // A的为(L-1,1)
    53         // 长度比a小1第一位为0
    54         // (例:11111……1110 )
    55     {
    56         n2 = l - 1;
    57         z2 = 1;
    58     }
    59     else
    60         for ( int i = 1 ; i < l ; i++ )// 从大到小枚举该长度下数,求得B
    61         {
    62             if (getnz(l, i) <= b)
    63             {
    64                 n2 = l;
    65                 z2 = i;
    66                 break;
    67             }
    68         }
    69     //n1,n2表示A,B长度     z1,z2 表示A,B中0的位置
    70     int ans;
    71     if (n1 > n2) ans = 0;  //ans = 0的情况
    72     else if (n1 == n2)  ans = (z1 - z2) + 1;
    73     else ans = (n1 + n2 - 2) * (n2 - n1 - 1) / 2 + z1 + n2 - z2;
    74     //  求得长度[n1+1,n2-1]中数字个数【 (n1 + n2 - 2) * (n2 - n1 - 1) / 2】
    75     // 长度n1中数字个数   【z1】
    76     // 长度n2中数字个数   【n2 - z2】
    77     cout << ans << endl;
    78 }
  • 相关阅读:
    Vue让水平滚动条(scroll bar)固定在浏览器的底部,并且同轴联动
    vue横向滚动条,初始化位置
    VUE父子组件传值,以及子组件调用父组件方法
    获取shell脚本所在路径而非执行路径
    免重装完整迁移ubuntu18.04系统方法
    auth.log大量出现pam_unix(cron:session): session opened for user root by (uid=0)解决办法
    禁用vim的visual模式方便拖选
    ssh端口反向代理与内网穿透
    mysql查询时将时间戳转换为时间格式
    浏览器打印控件分享
  • 原文地址:https://www.cnblogs.com/HITLJR/p/5964820.html
Copyright © 2020-2023  润新知