組合數學 Round Numbers

2021-09-26 03:01:13 字數 1672 閱讀 6815

給定乙個區間[l,r],問l到r的整數中有幾個轉換成二進位制數後0比1多(不計前導零)。

例如對於整數11,它二進位制拆分後是1011

1011

1011

按照上述過程進行拆分能得到多個不同的二進位制數:

1010(10

)1010(10)

1010(1

0), 1000(8

)1000(8)

1000(8

) , 0000(0

)0000(0)

0000(0

)它們互相組合,可以得到整個區間:

[

0000

,1000

)[0000,1000)

[0000,

1000

),[1000

,1010

)[1000,1010)

[1000,

1010

)以及1011

可以發現這樣就可以把1−n

1-n1−

n之間的數全都包含,這樣就可以用類似字首和的形式求出答案:

w or

k(r+

1)−w

ork(

l)

work(r+1)-work(l)

work(r

+1)−

work

(l)其中r+1

r+1r+

1,ll

l是因為work求的是比work()中的數小的數,是因為我們沒有把最後那個落單的整數算上去,只算到了[1,

n−1]

[1,n-1]

[1,n−1

]區間。

我們將二進位制處理出來之後,我們就可以列舉每一位,如果當前位是0,那麼就把0的總數加1,否則就將答案累加。

我們預處理出組合數cij

c_i^j

cij​

表示在i個可以選的位置中插入j個0的合法方案數

設二進位制長度為len

而上述過程計算的是長度等於len的方案數。

由於這裡是計算[1,

n−1]

[1,n-1]

[1,n−1

]之間所有的方案數,所以我們還要計算長度小於len的方案數。

雙重迴圈累加即可,過程與上述相似。

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

using

namespace std;

int l,r,len =0;

int c[

6060][

6060];

int a[

1010100];

void

init()

//預處理組合數

voidcl(

int x)

}//二進位制拆分處理

intwork

(int x)

signed

main()

}

//ps:tm的不知道為什麼,這題開long long會炸,大家千萬不能開long long!!!

組合數學 求組合數

對於求組合數,要根據所給資料範圍來選擇合適的演算法 這道題中所給的資料範圍適合用打表的方法直接暴力求解 先用4e6的複雜度預處理出所有的情況,再用1e4的複雜度完成詢問即可 include using namespace std const int n 2010 const int mod 1e9 ...

數學 組合數學

mod must be a prime const int mod 1e9 7 namespace combinatory ll inv ll x ll fac maxn invfac maxn void initc int n ll a ll n,ll m ll c ll n,ll m ll d ...

組合數學筆記

從n個數中選m個數,每個數至多選一次,方案數 性質 c n,0 c n,n 1 c n,m c n,n m c n,m c n 1,m 1 c n 1,m 楊輝三角 二項式展開 x y n i 0.n c n,i x iy n i 那這裡先說一下楊輝三角 前提 每行端點與結尾的數為1 每個數等於它上...