蓝桥杯国赛 二进制问题

这道题思路有两种,一种是数位DP,一种就是排列组合,这道题我用的是排列组合。

大致题意,用样例来说,1到7中,1的个数为2的有多少

0  |  0 0 0

1  |  0 0 1

2  |  0 1 0

3  |  0 1 1

4  |  1 0 0

5  |  1 0 1

6  |  1 1 0

7  |  1 1 1

 由此可看出来有3个,分别是3(011),5(101),6(110)。

对于二进制7来讲,我们可以分为三个区间进行排列组合,(111,110],(110,100],(100,000]。对于第一个区间,没有可以组合的方式,对于第二个区间只有一种组合的方式101,对于第三个区间也是只有一种011。

def C(a,b):  #组合排列
    ans=1
    for i in range(1,b+1):
        ans = int(ans * a / i)
        a-=1
    return ans

def getLen(x):   #求一个数转二进制后的长度,以及其中1的个数
    cnt,cnt1=0,0
    while x:
        if x&1:
            cnt1+=1
        x>>=1
        cnt+=1
    return cnt,cnt1

def lowbit(x):  #lowbit函数求出二进制数中最后的1
    return x&-x

N,K=map(int,input().split())
NLen,OneLen=getLen(N)
ans = 0

if OneLen == K: ans += 1 #因为我们的左区间是开区间,所以N需要特判
b=K-OneLen #有多少个位置可以填,111不仅没有,而且还多出一位所以为-1

while N:
    x=lowbit(N)
    N-=x
    b+=1
    a=getLen(x)[0]-1
    if b>=0:
        ans+=C(a,b)  #加上每一个区间符合条件的数量
print(ans)

 

你可能感兴趣的:(蓝桥杯,算法)