题目大意:统计区间[x,y]中在b进制下含k个1的数字个数。
数位dp。
具体见2009刘聪论文《浅谈数位类统计问题》...
1 #include<cstdio> 2 const int MAXN=32; 3 int f[MAXN][MAXN]; 4 void init() 5 { 6 f[0][0]=1; 7 for(int i=1;i<MAXN;++i) 8 { 9 f[i][0]=f[i-1][0]; 10 for(int j=1;j<=i;++j) 11 f[i][j]=f[i-1][j-1]+f[i-1][j]; 12 } 13 } 14 int tran(int x,int b) 15 { 16 int s[101]; 17 int p=0; 18 while(x) 19 { 20 s[p++]=x%b; 21 x/=b; 22 } 23 for(int i=p-1;i>=0;--i) if(s[i]>1) 24 { 25 for(int j=i;j>=0;--j) s[j]=1; 26 break; 27 } 28 int ans=0; 29 for(int i=0;i<p;++i) if(s[i]) ans|=1<<i; 30 return ans; 31 } 32 int cal(int x,int k) 33 { 34 int tot=0,ans=0; 35 for(int i=MAXN-1;i>=0;--i) 36 { 37 if(x&(1<<i)) 38 { 39 ++tot; 40 if(tot>k) break; 41 x^=1<<i; 42 } 43 if((1<<(i-1))<=x) 44 ans+=f[i-1][k-tot]; 45 } 46 if(tot+x==k) ++ans; 47 return ans; 48 } 49 int k,b,x,y; 50 int main() 51 { 52 scanf("%d%d%d%d",&x,&y,&k,&b); 53 init(); 54 x=tran(x,b);y=tran(y,b); 55 printf("%d\n",cal(y,k)-cal(x-1,k)); 56 return 0; 57 }