poj3252
第一道組合數學題,連跪一天。。
沒有discuss根本做不出來,但是想想不是很難。
首先,
RoundNumber[start, end] = RoundNumber[0,start] - RoundNumber[0,end - 1] = RoundNumber[0, start + 1] - RoundNumber[0, end]
這是容易證明的。因為一個數字是否是所謂“RoundNumber”,只跟它自己有關,也就是說轉化成二進制的0的個數是否大于1的個數有關。那么他們(獨立的數字,如1,2,3,4)之間是相互獨立的。至于為何要加一或者減一,因為是要包含區間邊界,無論是否小于等于它都會包含(省事兒),所以最后處理一下。
《組合數學》第二章“排列與組合”中,闡述了幾個原理:加法原理、減法原理、乘法原理。各自的前提是不同的,需要仔細去了解。
重點不在上面,上面只是基礎。
首先在高中我們學過組合數的定義:
然后它具有以下常用性質:
1.
2.
3.
4.
性質3常用于打表,因為其具遞推的性質。
切入正題,假設有如下二進制數:
問其是否是RoundNumber?答案是肯定的。
最一開始我們知道,要想求RN[start,end],我們只需要求RN[0,start+1]-RN[0,end]。歸根結底是求RN[0,x]。
把這個八位二進制數分情況討論一下,比它小的分兩種情況,一是1至7位數,二是八位數。
情況一:
一個二進制,長度為Len的數,若使0的個數大于1的個數,可以這么安排:
若Len是奇數,即Len=2*k+1,最高位是1,其余2k位,則有:
至此,Len是奇數時我們解決了。可以直接算這些組合數(從表中直接取,以下代碼就是這么操作的),也可以利用一下上面提供的性質。由性質2知,在性質1和式函數中,最頭的兩個是對稱相等的。那么,上式恰好等于:
若Len是偶數,Len=2*k,最高位是1,其余2k-1位,同理可得:
情況二:當位數為8時:
先放大一下這個二進制數:
可以清晰地看到,第四位,我標記了1。如果將1改為0,那么剩下的四位任意填數都滿足該數(新的)小于這個二進制數(10011000)B。但是不能任意填,還是要滿足0的個數大于1的個數,那么我們有如下結論:
令l為長度,i為當前改變的“1”的位置,如圖中的位置4,zero為0的計數(絕對計數、不包含被改變的第四位數1),a為需要填數的位置(下圖中的虛線框)中1的個數,b為需要填數的位置中0的個數。
有如下等式:
有如下不等式:
解得:
這個式子說明了,至少要填那么b個零,也就是l/2-(zero+1)。注意奇偶。至多呢?至多全填滿唄。填多少?i-1個(空格數)唄。注意,程序中是從高位到地位搜索,i的位置表示的是綠色的1的位置,i-1是空格(虛線框)的個數。
至此,問題解決了,那么代碼就很簡單了。
?
#include<iostream>using namespace std;int c[33][33] = { 0 }; int bin[35]; //十進制n的二進制數void combinations() {for (int i = 0; i <= 32; i++){for (int j = 0; j <= i; j++){if (!j || i == j){c[i][j] = 1;}else{c[i][j] = c[i - 1][j - 1] + c[i - 1][j];}}}return; }void dec_to_bin(int n) {bin[0] = 0;while (n){bin[++bin[0]] = n % 2;n /= 2;}return; }int round(int n) {int i, j;int sum = 0;dec_to_bin(n);/*計算長度小于bin[0]的所有二進制數中RN的個數*/for (i = 1; i < bin[0] - 1; i++){for (j = i / 2 + 1; j <= i; j++){sum += c[i][j];}}/*計算長度等于bin[0]的所有二進制數中RN的個數*/int zero = 0; //從高位向低位搜索過程中出現0的位的個數for (i = bin[0] - 1; i >= 1; i--){if (bin[i]){for (j = (bin[0] + 1) / 2 - (zero + 1); j <= i - 1; j++){sum += c[i - 1][j];}}else zero++;}return sum; }int main() {combinations();int a, b;while (cin >> a >> b){cout << round(b + 1) - round(a) << endl;} }
組合數學,一跪一天,爽!
?
?
轉載于:https://www.cnblogs.com/jiangu66/p/3243989.html
總結
- 上一篇: js在控件原有的事件方法中加入自己的方法
- 下一篇: [Idea Fragments]2013