题目描述
求给定区间 [X,Y] 中满足下列条件的整数个数:这个数恰好等于 KK 个互不相等的 BB 的整数次幂之和。例如,设 X=15,Y=20,K=2,B=2,则有且仅有下列三个数满足题意
输入格式
第一行包含两个整数 X 和 Y,接下来两行包含整数 K 和 B。
输出格式
只包含一个整数,表示满足条件的数的个数。
样例
样例输入
15 20
2
2
样例输出
3
数据范围与提示
对于全部数据,1≤X≤Y≤2^31−1,1≤K≤20,2≤B≤10。
______________________________________________________________________________________________
数位动归
一类区间统计问题,区间较大,无法用暴力求解或组合数学求解。
常见为求区间内满足某类条件的X进制数的个数。条件往往与数位有关。
此题:
首先,区间具有相减的性质。count[i...j]=count[ 0...j ] - count[ 0...i-1 ]。
这样问题就变成了0到i的x进制数有多少个满足条件。
因为是互不相等的k进制数,所以,转成k进制后,每个位上要么是0要么是1。
这样f[i][j]表示长度I的2进制数,有j个1的种类
f[i][j]=f[i-1][j]+f[i-1][j-1]
______________________________________________________________________________________________
1 #include<bits/stdc++.h> 2 using namespace std; 3 int x,y,k,b; 4 int wei[32]; 5 int f[32][32]; 6 void prech(int &x,int b) 7 { 8 int js=0; 9 while(x>0) 10 { 11 wei[++js]=x%b; 12 x/=b; 13 } 14 while(js>0) 15 { 16 if(wei[js]==1)x^=1<<(js-1); 17 else if(wei[js]>1) 18 { 19 for(int i=js;i>0;--i)x^=1<<(i-1); 20 break; 21 } 22 --js; 23 } 24 } 25 void dp() 26 { 27 f[0][0]=1; 28 for(int i=1;i<=31;++i) 29 { 30 f[i][0]=f[i-1][0]; 31 for(int j=1;j<=i;++j)f[i][j]=f[i-1][j]+f[i-1][j-1]; 32 } 33 } 34 int work(int x,int k) 35 { 36 int js=0,ans=0; 37 for(int i=31;i>0;--i) 38 { 39 if(x&(1<<i)) 40 { 41 ++js; 42 if(js>k)break; 43 x=x^(1<<i); 44 } 45 if((1<<(i-1))&x)ans+=f[i-1][k-js]; 46 } 47 if(js+x==k)ans++; 48 return ans; 49 } 50 int main() 51 { 52 scanf("%d%d%d%d",&x,&y,&k,&b); 53 x--; 54 prech(x,b);prech(y,b); 55 dp(); 56 cout<<work(y,k)-work(x,k); 57 return 0; 58 }