【序言】剛剛開始學,想找些簡單的題目入手,看到這題AC的人挺多,於是我也來做做這題。
【題目】
| Time Limit: 2000MS |
|
Memory Limit: 65536K |
| Total Submissions: 4732 |
|
Accepted: 1607 |
Description
The cows, as you know, have no fingers or thumbs and thus are unable to play Scissors, Paper, Stone' (also known as 'Rock, Paper, Scissors', 'Ro, Sham, Bo', and a host of other names) in order to make arbitrary decisions such as who gets to be milked first.
They can't even flip a coin because it's so hard to toss using hooves.
They have thus resorted to "round number" matching. The first cow picks an integer less than two billion. The second cow does the same. If the numbers are both "round numbers", the first cow wins,
otherwise the second cow wins.
A positive integer N is said to be a "round number" if the binary representation ofN has as many or more zeroes than it has ones. For example, the integer 9, when written in binary form, is 1001. 1001 has two zeroes and two ones; thus,
9 is a round number. The integer 26 is 11010 in binary; since it has two zeroes and three ones, it is not a round number.
Obviously, it takes cows a while to convert numbers to binary, so the winner takes a while to determine. Bessie wants to cheat and thinks she can do that if she knows how many "round numbers" are in a given range.
Help her by writing a program that tells how many round numbers appear in the inclusive range given by the input (1 ≤Start <Finish ≤ 2,000,000,000).
Input
Line 1: Two space-separated integers, respectively
Start and
Finish.
Output
Line 1: A single integer that is the count of round numbers in the inclusive range
Start..
Finish
Sample Input
2 12
Sample Output
6
【思路】
1.首先的想法,就是輸入一個數字n,能否令f(n)為那些≤n的"round numbers"的個數?那麼題目就可以轉化為f(Finish)-f(Start-1).
2.那麼如何求這個f(n)?
1)在求這個f(n)之前,先將n的二進位運算式求出來:(an)(an-1)...(a1)(a0). 當然這個an=1 (第一位是為1的)。後面以n=11,001,001為例做闡述(這是一個8位元)。
2)個人希望分別找出a)<10,000,000、b)10,000,000~11,000,000、c)11,000,000~11,001,000、d)11,001,000~11,001,001、e)10,101,001之間(左開右閉)的"round numbers"數,那問題不就迎刃而解了嗎?!
3)而a)可以對應成一個7位的“0”“1”串X,XXX,XXX,每一位上任意取0或者1,滿足count("0") >= count("1")的字串的個數.這個為C(7,0)+C(7,1)+...+C(7,3).
這裡稍作修改,a)對應成7位+首位是1的字串;6位+首位是1的字串;……;
b)可以對應成一個6位的“0”“1”串10,000,000+XXX,XXX,每一位上任意取0或者1,滿足count("0") +1>= count("1")+1(前2位是10)的字串的個數.這個為C(6,0)+C(6,1)+...+C(6,3).
c)d)類似,e)最後一位的情況特殊處理.
4)於是需要一個函數用於解決這樣的問題:一個k位的“0”“1”串XX...X,每一位上任意取0或者1,滿足count("0")+ZeroNum >= count("1")+OneNum的字串的個數。
於是定義一個函數用於解決這樣的問題。
int tempFunction(int k, int ZeroNum, int OneNum){int temp = ((k+ZeroNum+1-OneNum)%2 == 0) ? ((k+ZeroNum+1-OneNum)/2) : ((k+ZeroNum-OneNum)/2+1);//set the upper bound for count("1")//return C(k,0)+C(k,1)+...+C(k,temp-1)int sum = 0;if (temp <= 0){return 0;}for (int i = 0; i < temp; ++i){//楊輝三角的值已計算sum = sum + YangHuiTriangle[(k-1)*k/2+i-1];}return sum;}
其中楊輝三角的值可以用遞推公式計算
void InitialYangHuiTriangle(int *TriangleArray, int n)//n是組合數的一個參數,對應楊輝三角的時候,行數多1.{for (int i = 1; i <= n+1; ++i){for (int j = 1; j <= i; ++j){if ((j == 1) || (j == i) || (i == 1)){TriangleArray[(i-1)*i/2+j-1] = 1;}else{TriangleArray[(i-1)*i/2+j-1] = TriangleArray[(i-2)*(i-1)/2+j-2] + TriangleArray[(i-2)*(i-1)/2+j-1];}}}}
綜合以上的敘述,得到的如下程式:
【程式】
#include<iostream>using namespace std;int YangHuiTriangle[(1+25)*25/2];int SummateArray(int Array[], int n);void InitialYangHuiTriangle(int *TriangleArray, int n);int tempFunction(int, int, int);int RoundNumber(int);int main(){int StartNum;int FinishNum;cin >> StartNum >> FinishNum;InitialYangHuiTriangle(YangHuiTriangle, 24);cout << RoundNumber(FinishNum)-RoundNumber(StartNum-1)<<endl;return 0;}/******************************************************************************int RoundNumber(int aNumber)*函數作用:函數用來計算小於等於aNumber的"round number"的個數*函數輸入:十進位整數aNumber (0 <= aNumber <= 20,000,000)*函數輸出:小於等於aNumber的"round number"的個數*函數備忘:暫無*****************************************************************************/int RoundNumber(int aNumber){int countNumber = 0;if ((aNumber == 0)||(aNumber == 1)){return 0;}int BinaryNumber[24];int location = 0;while (aNumber != 1){BinaryNumber[location] = aNumber%2;location = location + 1;aNumber = aNumber/2;}BinaryNumber[location] = 1;//這樣就將十進位整數轉化為二進位表現形式,倒敘放在數組BinaryNumber[24]中//接下來是判斷1的位置int tempFirst1=location-1;while(tempFirst1 > 0){countNumber += tempFunction(tempFirst1,0,1);--tempFirst1;}int next = location - 1;//已經知道了location(>=1)對應的位置是1了,用next 用以記錄下一個1的位置int pre = location;while (next >= 0){if(next == 0)//此時表明這是最後一位{if(BinaryNumber[next] == 1)//此時pre的位置為1,next的位置也為1{countNumber += tempFunction(next, pre-next, 1);next -= 1;}else//表明這個數就是aNumber的二進位運算式,只需要驗證該數是否為round number 即可{if (2*SummateArray(BinaryNumber, location+1) <= (location + 1)){countNumber += 1;}next -= 1;}}else{if(BinaryNumber[next] == 1)//此時pre的位置為1,next的位置也為1{countNumber += tempFunction(next, pre-next, 1);pre = next;next -= 1;}else{next -= 1;}}}return countNumber;}int tempFunction(int k, int ZeroNum, int OneNum){if ( k==0 ){return 0;}int temp = ((k+ZeroNum+1-OneNum)%2 == 0) ? ((k+ZeroNum+1-OneNum)/2) : ((k+ZeroNum-OneNum)/2+1);//set the upper bound for count("1")//return C(k,0)+C(k,1)+...+C(k,temp-1)int sum = 0;if (temp <= 0){return 0;}for (int i = 0; i < temp; ++i){//楊輝三角的值已計算sum = sum + YangHuiTriangle[k*(k+1)/2+i];}return sum;}void InitialYangHuiTriangle(int *TriangleArray, int n)//n是組合數的一個參數,對應楊輝三角的時候,行數多1.{for (int i = 1; i <= n+1; ++i){for (int j = 1; j <= i; ++j){if ((j == 1) || (j == i) || (i == 1)){TriangleArray[(i-1)*i/2+j-1] = 1;}else{TriangleArray[(i-1)*i/2+j-1] = TriangleArray[(i-2)*(i-1)/2+j-2] + TriangleArray[(i-2)*(i-1)/2+j-1];}}}}/******************************************************************************int SummateArray(int Array[], int n)*函數作用:函數用來計算數組的所有元素的和*函數輸入:長度為n的數組Array*函數輸出:數組元素的和*函數備忘:暫無*****************************************************************************/int SummateArray(int Array[], int n){int sum = 0;for (int i = 0; i < n; ++i){sum = sum + Array[i];}return sum;}
【結果】 Runtime Error
【修改】 待續
這是從網上搜尋來的,發現思路類似,但是本人的比較拙劣
#include<iostream>using namespace std;int C[33][33];int MAX[33];int B[33];int tobinary(int b){int i=1;while(b) { B[i++]=b%2; b/=2;} return i-1;}void init(){ int i,j;C[1][0]=C[1][1]=1;for(i=2;i<=32;i++){ C[i][0]=1; for(j=1;j<=i;j++) C[i][j]=C[i-1][j]+C[i-1][j-1]; }MAX[1]=0; for(i=2;i<=32;i++) {for(j=(i+1)/2;j<i;j++) MAX[i]+=C[i-1][j]; }}int howmany(int n,int k,int *p) {if(k>=n||k<0) return 0; if((n==1&&k==0)||(n==2&&k==1)) return 1; if(p[n-1]==0) return howmany(n-1,k-1,p);elsereturn C[n-2][k-1]+howmany(n-1,k,p);}int compute(int n){int i,ans=0;int len=tobinary(n);for(i=(len+1)/2;i<len;i++)ans+=howmany(len,i,B);for(i=1;i<len;i++)ans+=MAX[i];return ans;}int main(){ init(); int start,finish;cin >> start >> finish; cout<<compute(finish)-compute(start-1)<<endl;return 0;}