思路
先说一下个人思路,由于时间原因我把这题跳了:区间[0,b]中的RN-区间[0,a-1]中的RN就是区间[a,b]中的RN,求所有小于k的RN的个数,可以先找出二进制中k的每一个1,然后在这些1之后的几位数字中填入n个1和m个0(m>=n),那么这些组合数的结果相加就是小于k的RN个数,答案就能求出来了。
下面这份代码与上面无关,题解转载自林厚从的数学一本通,注释也给你们打好了。
代码
#include<bits/stdc++.h> using namespace std; int c[33][33]={0}; int bin[35]; //十进制n的二进制数 void play_table(){ //打表计算C(n,m) for(int i=0;i<=32;i++){ for(int j=0;j<=i;j++){ if(!j||i==j) c[i][j]=1; else c[i][j]=c[i-1][j-1]+c[i-1][j]; } } return; } void dec_to_bin(int n){ //十进制n转换二进制,逆序存放到bin[] bin[0]=0; //b[0]是二进制数的长度 while(n){ bin[++bin[0]]=n%2; n/=2; } } int round(int n){ //计算比十进制数n小的所有RN数 int i,j,sum=0; //sum存储比十进制数n小的所有RN数 dec_to_bin(n); //计算长度小于bin[0]的所有二进制数中RN的个数 for(i=1;i<bin[0]-1;i++){ for(int j=i/2+1;j<=i;j++){ sum+=c[i][j]; //计算长度等于bin[0]的所有二进制数中RN的个数 } } int zero=0; //从高位向低位搜索过程中出现0的位的个数 for(i=bin[0]-1;i>=1;i--){ if(bin[i]){ //当前位为1 for(j=(bin[0]+1)/2-(zero+1);j<=i-1;j++){ sum+=c[i-1][j]; } }else zero++; } return sum; } int main(){ play_table(); int a,b; cin>>a>>b; cout<<round(b+1)-round(a)<<endl; return 0; }