主要考察组合数知识,初始化的时候参考公式
首先先推个公式,就是长度为len的Round Numbers的个数。
长度为len,第一位肯定是1了。
那么后面剩下 len-1位。
如果len-1是偶数。
那么 C(len-1,(len-1)/2+1)+C(len-1,(len-1)/2+2)+````C(len-1,len-1)
= ( 2^(len-1)-C(len-1,(len-1)/2) )/2;
如果len是奇数
那么就是 ( 2^(len-1) )/2
1 #include<cstdio> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<cmath> 6 #include<queue> 7 using namespace std; 8 const int maxn=35; 9 int m,t; 10 int c[maxn][maxn]; 11 int bit[maxn]; 12 void init() //初始化组合数 13 { 14 c[0][0]=c[1][0]=c[1][1]=1; 15 for(int i=2;i<=33;i++) 16 { 17 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 c[i][i]=1; 21 } 22 } 23 int calc(int n) //求小于等于n的round数的和 24 { 25 if(n<=1) return 0; 26 int len=0; 27 while(n>0) //求出该数的二进制表示 28 { 29 if(n&1) bit[len++]=1; 30 else bit[len++]=0; 31 n>>=1; 32 } 33 int ans=0; 34 for(int i=len-1;i>0;i--) //求出长度小于len的round数的和 35 { 36 if(i%2==0)ans+=((1<<(i-1)))/2; 37 else ans+=((1<<(i-1))-c[i-1][(i-1)/2])/2; 38 } 39 int c1=0,c0=0; 40 for(int i=0;i<len;i++) 41 { 42 if(bit[i]==0) c0++; 43 else c1++; 44 } 45 if(c0>=c1) ans++; //该数本身是round数 46 c1=1;c0=0; 47 for(int i=len-2;i>=0;i--) //注意计数是从零开始的 48 { 49 if(bit[i]==1) //该位可以变成零 50 { 51 for(int j=i;j>=0&&j+c0+1>=i-j+c1;j--) ans+=c[i][j]; //j是准备添加的0的数目 52 c1++; 53 } 54 else c0++; 55 } 56 return ans; 57 } 58 int main() 59 { 60 int i,j,k; 61 init(); 62 int a,b; 63 //freopen("1.in","r",stdin); 64 while(scanf("%d%d",&a,&b)!=EOF) 65 { 66 printf("%d\n",calc(b)-calc(a-1)); 67 } 68 return 0; 69 }
时间: 2024-10-19 12:14:16