• poj 3252 Round Numbers


    题目大意是:给你两个数n和m,计算从n到m的所有数的二进制中,0的个数大于1的个数的数的个数。

    这题用组合数学比较简单,不过要小心,很容易超时的,我就悲哀的RE了两次。

    对于一个长度为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));

    然后输入n和m,用cal(m)-cal(n-1)即可;

    代码如下:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <stdlib.h>
    
    using namespace std;
    
    int p[35],st[35];
    int n,m;
    
    int f(int n,int m)
    {
        int i,j,s;
        if(m>n-m)m=n-m;
        s=1;j=1;
        for(i=n-m+1;i<=n;i++)
        {
            s*=i;
            while(j<=m&&s%j==0)
            {
                s=s/j;
                j++;
            }
        }
        return s;
    }
    
    void init()
    {
        int i,j;
    
        memset(p,0,sizeof(p));
        p[1]=0;
        for (i=2;i<32;i++)
        for(j=1;j<=i-j;j++)
        p[i]+=f(i-1,j-1);
    }
    
    int cal(int n)
    {
        if(n<2) return 0;
        int i,j,s,x;
        x=n;
        int len=1;
        while(x)
        {
            x=x/2;
            len++;
        }
        len--;
        for(i=len;i>0;i--)
        {
            st[i]=n%2;
            n=n/2;
        }
        /*for(i=1;i<=len;i++)
        printf("%d ",st[i]);
        printf("\n");*/
        s=1;
        int s1=1;
        int s0=0;
        for(i=1;i<len;i++)
        s+=p[i];
        for(i=2;i<=len;i++)
        if(st[i])
        {
            if(s0+len-i>=s1+1)s++;
            for(j=1;j<=len-i&&s1+j<=len-(s1+j);j++)
            s+=f(len-i,j);
            s1++;
        }
        else
        s0++;
        return s;
    }
    
    int main()
    {
        init();
        cin>>n>>m;
        cout<<cal(m)-cal(n-1)<<endl;
        return 0;
    }

     

  • 相关阅读:
    Neo4j 第五篇:批量更新数据
    Neo4j 第四篇:使用.NET驱动访问Neo4j
    Neo4j 第三篇:Cypher查询入门
    Neo4j 第二篇:图形数据库
    Neo4j 第一篇:在Windows环境中安装Neo4j
    ElasticSearch入门 第九篇:实现正则表达式查询的思路
    ElasticSearch入门 第八篇:存储
    ElasticSearch入门 第七篇:分词
    ElasticSearch入门 第六篇:复合数据类型——数组,对象和嵌套
    Package 设计3:数据源的提取和使用暂存
  • 原文地址:https://www.cnblogs.com/misty1/p/2455840.html
Copyright © 2020-2023  润新知