上次哈工程校賽有乙個比較有趣的問題,我們一起來**一下!給乙個整數10,把10用二進位制表示為 1010,那麼10的二進位制表示中有2個1
那麼現在的問題是這樣的:給乙個整數n,然後問小於n的所有數中有多少個數它們的二進位制表示中有k個1。
快敲**,動作!
多組輸入,每組兩個整數n,k(n<1000000000,k<20)
輸出結果
10 25 1
43
其實現在看看也沒那麼難啊==不過讓我想到了大學前兩年中鬧心指數排第二的工程校賽t^t
hints:1.二進位制的特性:若找比某數小的數的二進位制,小數最高位取0,則其他位上0.1隨意,所以是排列組合即某位由0變成1,這個數一定變小!2.用楊輝三角求組合數3.本題演算法是從高向低遍歷,取該位為0,比該位大的都是1,比他小的排列組合~因為該位由1到0,而隨著迴圈的進行該位被強制設成1,所以不涉及到相加會重複的情況。4.注意!!從高到低遍歷時是--不是++
這道題如果資料量再小點,比如n<1000000。那麼就可以打表預處理0~1000000的資料,然後再查詢即可。但是現在n<1000000000。 打表會超時,只能另外想辦法了。
有一種思路:
eg: n=30,k=3
(1)將n二進位制表示為 1 1 1 1 0,用ans表示要求的結果 ,初始化ans=0;
(2)二進位制表示一共有5位,從最高位開始列舉 for(int i=5;i>=1;i--)
(3)當列舉到第i位時,我們用sum表示第i+1位到最高位這之間的『1』的個數,如果第i位是『1』,我們就把這個『1』抹成『0』,那麼就可以得到 從後面的i-1位中取出k-sum的方法數(ans+=c(i-1,k-sum))
(4)要注意的是在列舉過程中,一旦發現sum==k了,就要(ans++,break),結束列舉,最後的ans即為所求。
#include#include#includeusing namespace std;
int a[1000];
int sum[1000];
int b[100][100];
int n,k,cnt;
void ssum(int n)
memset(sum,0,sizeof(sum));
for(int i=cnt;i>=1;i--)
//return cnt;
}void init()
if(i-1>=tmp)}}
printf("%d\n",all);
}}
數字DP 數字統計
題目 給定兩個正整數a和b,求在 a,b 中的所有整數中,每個數碼 digit 各出現了多少次。數字dp 1 分情況,逐位討論。2 模型 計算在 l,r 中有多少個數滿足條件。3 套路 將問題轉化為 1,r 1,l 1 只需回答 1,x 的詢問即可。思路1.算出 1,x 1 按位拆分,為後面做鋪墊 ...
數字統計 區間數字
time limit 1 sec memory limit 128 mb submit 8 solved 3 submit status web board 一本書的頁碼從自然數1 開始順序編碼直到自然數n。書的頁碼按照通常的習慣編排,每個頁碼都不含多餘的前導數字0。例如,第6 頁用數字6 表示,而...
數字統計小結
在資訊學競賽中,有這樣一類問題 求給定區間中,滿足給定條件的某個d 進製數或此類數的數量。所求的限定條件往往與數字有關,例如數字之和 指定數碼個數 數的大小順序分組等等。題目給定的區間往往很大,無法採用樸素的方法求解。此時,我們就需要利用數字的性質,設計log n 級別複雜度的演算法。解決這類問題最...