zoukankan      html  css  js  c++  java
  • poj3252(组合数)

    题目链接:http://poj.org/problem?id=3252

    题意:给定s、e,求[s,e]之间的Round Number的个数,RN数为二进制表示中0的个数大于1的个数的数,s、e<=2e9。

    思路:计算[s,e]之间的RN数等价于getn(e+1)-getn(s),getn(s)表示[0,s)之间的RN数,注意RN数要求是正数,所以0不算,但其实算不算结果都一样。需要用到组合数,初始化组合数,用公式C(n,m)=C(n-1,m-1)+C(n-1,m)递推实现,用sum[i]表示长度为i的数中RN数的个数。用bit数组存储x的各个位的值,len表示其长度。则小于x的RN数分两种情况,一种长度小于len的,此情况的数恒小于x,但要注意的是数的第一位必须是1。长度小于len的情况比较简单,只需要把预处理的sum数组相加即可; 等于len的情况,从第二位开始讨论,一直到第len位,若为1,则通过组合数计算出这一位取0时有多少个RN数并加上,若为1,则跳过。

    AC代码:

     1 #include<cstdio>
     2 using namespace std;
     3 
     4 int s,e;
     5 int C[35][35],sum[35];
     6 
     7 void init(){
     8     C[0][0]=1;
     9     for(int i=1;i<=32;++i)
    10         C[i][0]=C[i][i]=1;
    11     for(int i=2;i<=32;++i)
    12         for(int j=1;j<=i-1;++j)
    13             C[i][j]=C[i-1][j-1]+C[i-1][j];
    14     for(int i=2;i<=32;++i)
    15         for(int j=(i+1)>>1;j<=i-1;++j)
    16             sum[i]+=C[i-1][j];
    17 }
    18 
    19 int getn(int x){
    20     if(x<=1) return 0;
    21     int ans=0,len=0,num0=0,num1=1,bit[35];
    22     while(x){
    23         bit[len++]=x%2;
    24         x/=2;
    25     }
    26     for(int i=2;i<len;++i)
    27         ans+=sum[i];
    28     for(int i=len-2;i>=0;--i)
    29         if(bit[i]){
    30             for(int j=i;j>=0&&j+num0+1>=num1+i-j;--j)
    31                 ans+=C[i][j];
    32             ++num1;
    33         }
    34         else
    35             ++num0;
    36     return ans;
    37 }
    38 
    39 int main(){
    40     init();
    41     scanf("%d%d",&s,&e);
    42     printf("%d
    ",getn(e+1)-getn(s));
    43     return 0;
    44 }
  • 相关阅读:
    第六周学习总结
    20165227 《Java程序设计》实验一(Java开发环境的熟悉)实验报告
    第五周学习总结
    20165227 20165228结对学习感想
    第四周课堂测试补做
    第四周作业
    20165227第三周学习总结
    第二周学习总结
    20165304《JAVA程序设计》第四周学习总结
    20165304 2017-2018-2 《Java程序设计》第3周学习总结
  • 原文地址:https://www.cnblogs.com/FrankChen831X/p/10684127.html
Copyright © 2011-2022 走看看