poj 3252 Round Numbers 【推導·排列組合】

來源:互聯網
上載者:User

標籤:os   art   for   io   c++   amp   

 以sample為例子
 [2,12]區間的RoundNumbers(簡稱RN)個數:Rn[2,12]=Rn[0,12]-Rn[0,1]
 即:Rn[start,finish]=Rn[0,finish]-Rn[0,start-1]
 所以關鍵是給定一個X,求出Rn[0,X]
 現在假設X=10100100 
 這個X的二進位總共是8位,任何一個小於8位的二進位都小於X
 第一部分,求出長度為[0,7]區間內的二進位是RoundNumber的個數
  對於一個長度為Len的二進位(最高位為1),如何求出他的RoundNumbers呢(假設為用R(len)來表達),分為奇數和偶數兩種情況
  1、奇數情況:在Len=2k+1的情況下,最高位為1,剩下2k位,至少需要k+1為0
   用C(m,n)表示排列組合數:從m個位置選出n個位置的方法
   R(len)=C(2k,k+1)+C(2k,k+2)+...+C(2k,2k).
   由於 A:C(2k,0)+C(2k,1)+...+C(2k,2k)=2^(2k)
     B:C(2k,0)=C(2k,2k), C(2k,1)=C(2k,2k-1) ,,C(2k,i)=C(2k,2k-i)
   於是  C(2k,0)+C(2k,1)+...+C(2k,2k)
    = C(2k,0)+C(2k,1)+...+C(2k,k)+C(2k,k+1)+C(2k,K+2)+...+C(2k,2k)
    = 2*R(len)+C(2k,k)
    =2^(2k)
    所以R(len)=1/2*{2^(2k)-C(2k,k)};
  2. 偶數情況 len=2*k,類似可以推到 R(len)=1/2*(2^(2k-1));
 第二部分,對於上面這個長度為8的例子:即X=10100100,首先如果本身是RoundNumbers,第二部分的結果總數+1
  第一部分已經將長度小於8的部分求出。現在要求長度=8的RoundNumber數目
  長度為8,所以第一個1不可改變
  現在到第二個1,如果Y是首碼如100*****的二進位,這個首碼下,後面取0和1必然小於X,已經有2個0,一個1,剩下的5個數字中至少需要2個0,
   所以把第二個1改為0:可以有C(5,2)+C(5,3)+C(5,4)+C(5,5)
  現在第三個1,也就是前最為101000**,同樣求出,至少需要0個0就可,所以有C(2,0)+C(2,1)+C(2,2)個RoundNumbers
  。。。
  將所有除了第一個1以外的1全部變為0,如上算出有多少個RoundNumbers,結果相加(由於首碼不一樣,所以後面不管怎麼組合都是唯一的)

 將第一部分和第二部分的結果相加,就是最後的結果了。
 精度要求方面,用int就可以了:two billion=20億<2*1024*1024*1024=2^31,需用31位來表示數組,由於第一位總是1,所以求組合數的時候最多求30,C(30,k),k取值區間是[0,30],因為C(k,i)<2^k,所以結果用int表示就可以

 


Problem: 3252  User: ycdoit
Memory: 148K  Time: 0MS
Language: C++  Result: Accepted
#include<iostream>
using namespace std;
const int MS=31;
int C[MS][MS];        //[0,...30]
int power2[MS];        //1 2 4 8 ... 2^(MS-1)
int Binary[MS];
int Solve(int X){
    if(X<=1)    return 0;
    int i,j,k,n0,n1,Len,res=0;
    for(i=0;i<MS;++i)    Binary[i]=((power2[i]&X)!=0)?1:0;
    for(i=MS-1;i>=0 && Binary[i]==0;--i);    //停止的時候,i指向1        //總長度為i+1
    for(Len=i;Len>=1;--Len){        //求出 [1...i]的R(len)
        if(Len%2==1)    res+=(( power2[Len-1]-C[Len-1][(Len-1)/2])>>1);
        else    res+=(power2[Len-1]>>1);
    }
    for(j=i,n0=0,n1=0;j>=0;--j)    if(Binary[j])    ++n1;    else ++n0;
    if(n1<=n0)    ++res;
    for(j=i-1,n0=0,n1=1;j>=0;--j)    {
        if(Binary[j]){    //後面還有j位    第j位臨時當做0
            for(k=j;k>=0 && k+n0+1>=j-k+n1;--k)        res+=C[j][k];
            ++n1;
        }
        else ++n0;
    }
    return res;
}
int main(){
    int i,j,Start,Finish;
    for(i=0;i<MS;++i)    C[i][0]=1,C[i][i]=1,power2[i]=(1<<i);
    for(i=2;i<MS;++i)    for(j=1;j<i;++j)    C[i][j]=C[i-1][j-1]+C[i-1][j];
    scanf("%d%d",&Start,&Finish);
    printf("%d\n",Solve(Finish)-Solve(Start-1));
    return 0;
}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.