题意:给定x,y,K,B,要求找出在区间[x,y]内的正整数个数,使它们满足恰好由K个不同的某个B的幂组成
例如
X=15, Y=20, K=2, B=2
17 = 24+20,
18 = 24+21,
20 = 24+22. 有三个正整数满足要求
把问题转化一下,设g(x)为有多少个<=x的正整数满足题意,那么原题差分一下=g(y)-g(x-1)
现在解决转化之后的问题,把x进行B进制展开,目标是得到一个B进制串使它只含0和1,并且小于等于x,可以用动态规划来解决
用f[i][j][flag]表示进行到第i位,有j个1,flag=0,1分别表示小于,等于时的满足要求的总数,递推式容易得到,从高位到低位递推,注意细节。
最后答案为f[1][k][0]+f[1][k][1](这里1为最低位)
1 #include <iostream> 2 #include <cstring> 3 using namespace std; 4 int x,y,k,b; 5 int len,Bbas[51]; 6 int f[51][21][2]; //1 等于 0 小于 7 int solve(int p){ 8 len=0;memset(Bbas,0,sizeof(Bbas)); 9 memset(f,0,sizeof(f)); 10 int t=p; 11 while (t){ 12 Bbas[++len]=t%b;t=t/b; 13 } 14 if (Bbas[len]==1) {f[len][1][1]=1;f[len][0][0]=1;} 15 else {f[len][1][0]=1;f[len][0][0]=1;} 16 for (int i=len-1;i>=1;i--) 17 for (int j=0;j<=k;j++){ 18 if (j==0) { 19 f[i][j][0]=1; 20 }else { 21 if (Bbas[i]>1) { 22 f[i][j][0]=f[i+1][j-1][1]+f[i+1][j-1][0]+f[i+1][j][1]+f[i+1][j][0]; 23 }else { 24 if (Bbas[i]==1) { 25 f[i][j][0]=f[i+1][j][1]+f[i+1][j][0]+f[i+1][j-1][0]; 26 f[i][j][1]=f[i+1][j-1][1]; 27 } 28 if (Bbas[i]==0) { 29 f[i][j][0]=f[i+1][j][0]+f[i+1][j-1][0]; 30 f[i][j][1]=f[i+1][j][1]; 31 } 32 } 33 } 34 } 35 return f[1][k][0]+f[1][k][1]; 36 } 37 int main(){ 38 cin>>x>>y>>k>>b; 39 cout<<solve(y)-solve(x-1)<<endl; 40 return 0; 41 }
时间: 2024-10-07 06:28:56