本质上是暴力模拟计算,逐位统计、以及如何寻找不被约束的状态来简化计算 是关键点。
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; }