20140708testA

首先想到打表.....

2x10^9坑定是不行的.....我隔壁是血淋淋的教训——3.6G

于是我想到了按位数来分0 1的个数。但最后推出来2*10^9都才30000多,绝对是错了。后来才知道应该排列组合。

只不过这次找到一个10转2的函数itoa(num,char,2) 如果想用整形数,用atoi(itoa(num,char,2))。

之后判断1的个数,最朴素的是扫一遍。

这里有种与n无关,只与1的个数有关的判断法

1 int BitCount2(unsigned int n)
2 {
3     unsigned int c =0 ;
4     for (c =0; n; ++c)
5     {
6         n &= (n -1) ; // 清除最低位的1
7     }
8     return c ;
9 }
View Code

但正解其实并非如此......将一定位数的方数用组合数做出来后,再按位进行加减

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <iostream>
 4 
 5 using namespace std;
 6 
 7 int a[40] ;
 8 int c[40][40] ;
 9 
10 void prework()
11 {
12     memset(c,0,sizeof(c));
13     c[0][0] = 1 ;
14     c[1][0] = c[1][1] = 1 ;
15     for (int i=2;i<40;i++)
16     {
17         c[i][i] = c[i][0] = 1;
18         for (int j=1;j<i;j++)
19             c[i][j]=c[i-1][j]+c[i-1][j-1] ;
20     }
21 }
22 
23 int work(int x)
24 {
25     if (x==0) return 0;
26     int cn=0,ret=0;
27     while (x) a[cn++]=x&1 , x>>=1 ;
28     for (int pos=0;pos<cn-1;pos++)
29         for (int z=pos;z>=0&&z>=pos-z+1;z--)
30             ret+=c[pos][z] ;
31     int now_one=1;
32     for (int i=cn-2;i>=0;i--)
33     {
34         if (a[i]==1)
35         {
36             int now_zero=cn-i-now_one ;
37             for (int j=i;j>=0&&now_zero+j>=now_one+i-j;j--)
38                 ret+=c[i][j] ;
39             now_one++ ;
40         }
41     }
42     if (cn-now_one>=now_one)ret++ ;
43     return ret ;
44 }
45 int l,r;
46 int main()
47 {
48    // freopen("testA.in","r",stdin);
49    // freopen("testA.out","w",stdout);
50     prework() ;
51     scanf("%d%d",&l,&r); 
52     printf("%d",work(r)-work(l-1));
53     return 0 ;
54 }
View Code

 

posted @ 2014-07-08 19:18  woshizyj  阅读(180)  评论(0编辑  收藏  举报