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 }

      

  • 相关阅读:
    阿里云CentOS安装firefox闪退
    error: QApplication: No such file or directory
    CentOS下自动登陆root帐户
    Linux下常用软件
    【记录】haphost免费vps初始配置
    检测Linux VPS是Xen、OpenVZ还是KVM真假方法
    使用VNC远程管理VPS(Centos系统)
    配置suricata
    NGUI的输入框制作(attach- input filed script的使用)
    NGUI技能CD效果制作(sprite的type:filled)
  • 原文地址:https://www.cnblogs.com/Lyush/p/2156753.html
Copyright © 2011-2022 走看看