/* 调了半晚上了...... 感觉是凑出来的QAQ 不过也还好思路比较清晰 数位dp f[i]表示i位的二进制数中 有几个合法的(默认开头一个是1) 然后求[1,L] [1,R+1] 首先位数小的都行 关键是位数一样的 这里还要保证数值比他小 比如 110100循环高位到低位 变成 10****统计****位的就好了 这样就保证比他小 程序里那两个reverse啥的可以无视 后期写的蒙蔽了 有点混乱 QAQ */ #include<cstdio> #include<algorithm> #include<cstring> using namespace std; int a,b,f[50][50]; int Cal(int n,int m){ int r=1; for(int i=1;i<=m;i++){ r*=(n-i+1);r/=i; } return r; } void Get(){ f[0][0]=1; for(int i=1;i<=35;i++) for(int j=0;j<=i;j++) f[i][j]=Cal(i,j); } int sol(int x){ int data[35]={0},c[35]={0}; int r=0,len=0; while(x){ data[++len]=x%2;x/=2; } memcpy(c,data,sizeof(data)); reverse(c+1,c+1+len); for(int i=1;i<=len;i++) c[i]=c[i-1]+c[i]; for(int i=1;i<len;i++) for(int j=0;j<=i/2-1;j++) r+=f[i-1][j]; reverse(c+1,c+1+len); for(int i=len-1;i>=1;i--)if(data[i]) for(int j=0;j+c[i+1]<=len/2;j++) r+=f[i-1][j]; return r; } int main() { scanf("%d%d",&a,&b);Get(); printf("%d\n",sol(b+1)-sol(a)); return 0; }
原文:http://www.cnblogs.com/yanlifneg/p/5947451.html