zoukankan      html  css  js  c++  java
  • HDU2502 月之数 组合数

    月之数

    Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
    Total Submission(s): 2744    Accepted Submission(s): 1585


    Problem Description
    当寒月还在读大一的时候,他在一本武林秘籍中(据后来考证,估计是计算机基础,狂汗-ing),发现了神奇的二进制数。
    如果一个正整数m表示成二进制,它的位数为n(不包含前导0),寒月称它为一个n二进制数。所有的n二进制数中,1的总个数被称为n对应的月之数。
    例如,3二进制数总共有4个,分别是4(100)、5(101)、6(110)、7(111),他们中1的个数一共是1+2+2+3=8,所以3对应的月之数就是8。
     


    Input
    给你一个整数T,表示输入数据的组数,接下来有T行,每行包含一个正整数 n(1<=n<=20)。
     


    Output
    对于每个n ,在一行内输出n对应的月之数。
     


    Sample Input
    3 1 2 3
     


    Sample Output
    1 3 8
     
      该题题义简单,是求一个二进制数的区间内,1的个数,不知到有木有更好的办法,写这道题时想到的就是一个组合问题。
      比如要求一个4二进制数的月之数是多少,由于第一位必须为1,所以有多少个3位的二进制数,就有多少个高位1,后面的就是从N-1个里面选一个,两个...... 这样的组合数,在具体计算过程中还要考虑奇偶性。
      代码如下:
     1 #include <cstdio>
    2 #include <cstring>
    3 #include <cstdlib>
    4 using namespace std;
    5
    6 long long mix( long long n, long long m )
    7 {
    8 long long res = 1;
    9 for( long long i = 0; i < m; ++i )
    10 { // 一直用这个学来的方法来防止溢出
    11 res *= ( n - i );
    12 res /= ( i + 1 );
    13 }
    14 return res;
    15 }
    16
    17 int main()
    18 {
    19 int T;
    20 scanf( "%d", &T );
    21 while( T-- )
    22 {
    23 long long N, ans = 1;
    24 scanf( "%I64d", &N );
    25 for( long long i = 1; i <= N - 1; ++i )
    26 {
    27 ans <<= 1;
    28 }
    29 if( ! ( N & 1 ) )
    30 {
    31 int lim = N / 2 - 1;
    32 for( long long i = 1; i <= lim; ++i )
    33 {
    34 ans += ( N - 1 ) * mix( N - 1, i );
    35 }
    36 ans += ( N - 1 );
    37 }
    38 else
    39 {
    40 int lim = ( N - 1 ) / 2;
    41 for( long long i = 1; i < lim; ++i )
    42 {
    43 ans += ( N - 1 ) * mix( N - 1, i );
    44 }
    45 ans += ( N - 1 ) / 2 * mix( N - 1, ( N - 1 ) / 2 );
    46 ans += ( N - 1 );
    47 }
    48 printf( "%I64d\n", ans );
    49 }
    50 return 0;
    51 }

      突然想到用移位判定奇偶来统计1的个数,现在就去试试看。

      上面的这种方法也能过,代码量下来了,但是速度慢了 78MS, 前面的是0MS。代码如下:

     1 #include <cstring>
    2 #include <cstdlib>
    3 #include <cstdio>
    4 using namespace std;
    5
    6 int main()
    7 {
    8 int T;
    9 scanf( "%d", &T );
    10 while( T-- )
    11 {
    12 int N, beg = 1, end = 1, ans = 0;
    13 scanf( "%d", &N );
    14 for( int i = 1; i < N; ++i )
    15 beg <<= 1, end <<= 1;
    16 end <<= 1, end -= 1;
    17 for( int i = beg; i <= end; ++i )
    18 {
    19 int t = i;
    20 while( t > 0 )
    21 {
    22 if( t & 1 )
    23 ++ans;
    24 t >>= 1;
    25 }
    26 }
    27 printf( "%d\n", ans );
    28 }
    29 return 0;
    30 }

      还有一种递推解法,个人觉得很好很强大。 代码如下:

     1 #include <cstdio>
    2 #include <cstring>
    3 #include <cstdlib>
    4 using namespace std;
    5
    6 int ans[22], base = 1;
    7
    8 int main()
    9 {
    10 ans[1] = 1;
    11 for( int i = 2; i <= 20; ++i )
    12 {
    13 ans[i] = 2 * ans[i-1] + base;
    14 base <<= 1;
    15 }
    16 int T;
    17 scanf( "%d", &T );
    18 while( T-- )
    19 {
    20 int N;
    21 scanf( "%d", &N );
    22 printf( "%d\n", ans[N] );
    23 }
    24 return 0;
    25 }

      

  • 相关阅读:
    macbook 无声音解决方案
    webapck dev server代理请求 json截断问题
    百度卫星地图开启
    服务器 nginx配置 防止其他域名绑定自己的服务器
    记一次nginx php配置的心路历程
    遇到npm报错read ECONNRESET怎么办
    运行svn tortoiseSvn cleanup 命令失败的解决办法
    svn add 命令 递归目录下所有文件
    m4出现Please port gnulib freadahead.c to your platform! Look at the definition of fflush, fread, ungetc on your system, then report this to bug-gnulib."
    Ubuntu下安装GCC,mpc、mpfr、gmp
  • 原文地址:https://www.cnblogs.com/Lyush/p/2156753.html
Copyright © 2011-2022 走看看