#P2984. USACO(38)数位2:二进制编号来源[Cow Queueing, 2003 Dec]【SP1182】

USACO(38)数位2:二进制编号来源[Cow Queueing, 2003 Dec]【SP1182】

Description

 





测试数据的A和B为2进制

100
1111
5
1001

Hint

by hansang:
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=45;
char s1[N], s2[N]; LL d[N], c[N][N], ans[N];
LL dfs(LL x, LL t, LL k){
    if(t==0 && k==0) return 1;
    if(x<0 || t==0 || k<0) return 0;
    if(x&d[t-1]) return c[t-1][k]+dfs(x, t-1, k-1);
    else return dfs(x, t-1, k);
}
int main(){
    d[0]=1; for(int i=1; i<=40; i++) d[i]=d[i-1]*2;
    memset(c, 0, sizeof(c)); c[0][0]=1;
    for(int i=1; i<=40; i++){
        c[i][0]=1;
        for(int j=1; j<=i; j++) c[i][j]=c[i-1][j]+c[i-1][j-1];
    }
scanf("%s%s"&#44; s1+1&#44; s2+1);
LL K&#44; A=0&#44; B=0; scanf("%lld"&#44; &amp;K);
int len1=strlen(s1+1)&#44; len2=strlen(s2+1);
for(int i=len1; i&gt;=1; i--){
    A+=(s1[len1-i+1]-'0')*d[i-1];
}
for(int i=len2; i&gt;=1; i--){
    B+=(s2[len2-i+1]-'0')*d[i-1];
}
if(A&gt;B) swap(A&#44; B);
LL sum=0&#44; t=0&#44; k;
for(int i=0; i&lt;32; i++){
    LL x=dfs(B&#44; 32&#44; i)-dfs(A-1&#44; 32&#44; i);
    if(sum+x&lt;K) sum+=x&#44; t=i;
    else {k=K-sum; break;}
}
 
t++;
LL l=A&#44; r=B&#44; x=dfs(A-1&#44; 32&#44; t)&#44; res=0;
while(l&lt;=r){
    LL mid=(l+r)/2;
    if(dfs(mid&#44; 32&#44; t)-x&gt;=k) r=mid-1&#44; res=mid;
    else l=mid+1;
}
int len=0;
while(res&gt;0) ans[++len]=res%2&#44; res/=2;
for(int i=len; i&gt;=1; i--) printf("%d"&#44; ans[i]);
printf("\n");
return 0;

}

</p>