数位dp题,关键是用树的思维去考虑。
对于一个数字X,要是能表示成K个B的不同次幂,等价于X在B进制下有且只有K个位上面的数字为一,其他位上的数字都为0。
具体读者可以去参考,国家集训队李聪的论文,里面的介绍都很详细。
#include<stdio.h> #include<string.h> #define LL long long LL c[60][60]; int K,b,a[40]; void init()//预处理组合数 { int i,j; for(i=0;i<40;i++)c[i][0]=c[i][i]=1; for(i=1;i<40;i++) for(j=1;j<i;j++) c[i][j]=c[i-1][j]+c[i-1][j-1]; } int change(int s) { int i,j,len; memset(a,0,sizeof(a)); for(i=0;s;i++){ a[i]=s%b; s/=b; } len=i; for(i=len;i>=0;i--){//对于非二进制的处理 if(a[i]>1){ for(j=i;j>=0;j--)a[j]=1; break; } } return len; } int solve(int s) { int ans=0; int i,j; int len=change(s); int tot=0; for(j=len+1;j>0;j--) { if(a[j]){ tot++; if(tot>K)break; } if(a[j-1])ans+=c[j-1][K-tot]; } if(a[0]+tot==K)ans++;//考虑本身 return ans; } int main() { int i,j,x,y; init(); while(scanf("%d%d",&x,&y)!=-1) { scanf("%d%d",&K,&b); printf("%d ",solve(y)-solve(x-1)); } return 0; }