1221.数1
Time Limit: 1000 MS
Memory Limit: 65536 K
Total Submissions: 248 (53 users) Accepted: 34 (26 users)
[ My Solution ]
Total Submissions: 248 (53 users) Accepted: 34 (26 users)
[ My Solution ]
Description
输入正整数x、y、k。求区间[x, y]中转换成二进制后含有k个1的数的个数,比如x=3,y=10,k=2,则转换成二进制后含有2个1的数有5个(3、5、6、9、10)。
0<x<=y<=1000,000,000,0<=k<=30。
Input
首先是一个正整数T,表示有T组数据, 0<T<=10。
接下来每组数据输入三个正整数x,y,k,分别如上表示。
Output
对应每组数据输出结果
Sample Input
1
3 10 2
Sample Output
5
很简单,就是求C(n,m)
比如10里的二进制1个数为2的:
10二进制:1010 有1个数cnt=2
则不大于10的二进制1个数为2的个数
sum=C(1,1)+C(3,2)=4;
10也满足,故sum=sum+1=5
[n,m]的答案就是sum(m)-sum(n)
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int C(int n,int m){//C(n,m)
if(m<0||m>n)return 0;
int h=(n-m)<m?(n-m):m;
int i,r=1;
for(i=1;i<=h;i++){
r*=n;
r/=i;
n--;
}
return r;
}
int get(int n,int k,bool b){
// cout<<"【"<<n<<"】"<<endl;
int a[30]={0};
int i,l=0,cnt=0,sum=0;
while(n){
if(n&1){
cnt++;//1的个数
a[l]=1;
}
n>>=1;
l++;
}
n=0;
if(b&&cnt==k)sum++;
for(i=0;i<l;i++){
if(a[i]==1){//c(i,k-(sum-m))
n++;
sum+=C(i,k-cnt+n);
// cout<<i<<"----"<<(k-cnt+n)<<"="<<C(i,k-cnt+n)<<endl;
}
}
return sum;
}
int main(){
int T,n,m,k;
cin>>T;
while(T--){
cin>>n>>m>>k;
n=get(n,k,false);
m=get(m,k,true);
k=m-n;
//cout<<n<<"-----"<<m<<endl;
cout<<k<<endl;
}
return 0;
}