本质上是暴力模拟计算,逐位统计、以及如何寻找不被约束的状态来简化计算 是关键点。

  1. 树形结合, 按位统计. 若当前位为1, 则取0, 剩下的位任意取都比其小, ans += f[ L ][ k-tot ],  L表示剩下长度. 论文这个地方写的感觉不对- -...

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<string>
#include<algorithm>
using namespace std;

int f[32][32];

void init(){
    memset(f,0,sizeof(f));    
    f[0][0] = 1;
    for(int i = 1; i <= 31; i++){
        f[i][0] = f[i-1][0];
        for(int j = 1; j <= i; j++)
            f[i][j] = f[i-1][j-1] + f[i-1][j];
    }
}
int get(int n,int b){
    string s;
    while( n ){
        s = char((n%b)+'0') + s;
        n /= b;
    }
    for(int i = 0; i < (int)s.size(); i++){
        if( s[i]-'0' > 1 ){
            for(int j = i; j < (int)s.size(); j++)
                s[j] = '1';
            break;    
        }    
    }
    int x = 0;
    for(int i = 0; i < (int)s.size(); i++)
        x = (x<<1)|(s[i]-'0');
    return x;
}
int calc(int n,int k){
    int tot = 0, res = 0;
    for(int i = 30; i >= 0; i--){
        if( (n&(1<<i)) ){
            if( tot <= k )    
                res += f[i][(k-tot)];    
            tot += 1;    
        }    
    }    
    if( tot == k ) res++;
    return res; 
}
int main(){
    init();    
    int x, y, b, k;
    scanf("%d%d%d%d",&x,&y,&k,&b);
    x = get(x,b), y = get(y,b);
    printf("%d\n", calc(y,k) - calc(x-1, k) );
    return 0;
}
View Code

相关文章: