 /**//*
两种操作
1)询问[x,y]区间内,base进制下,一个数的各位之和为M的个数
2)询问[x,y]区间内,第K大各位之和为M的数
数位统计,预处理dp[len][j]在base进制下,长度为len各位之和为j的个数
然后逐位统计
对于2)需要二分,注意的是(high+low)会超int,要用long long,不然超时
很阴的是输入的X可能>Y , hdu的 assert() RE是返回wa的
*/
#include<cstdio>
#include<cstring>
#include<algorithm>

using namespace std;

const int MAXN = 310;

int dp[40][MAXN];

void init(int base , int limit)
  {
memset(dp,0,sizeof(dp));
dp[0][0] = 1;
for(int i = 1; i <= 31 ; i++)
 {
for(int j = 0 ; j <= limit ; j++)
for(int k = 0; k < base && j - k >= 0 ; k++)
dp[i][j] += dp[i-1][j-k];
}
}

int cal(int x, int base , int M)//cal [1,x)
  {
int bit[40] , len = 0;
while(x)
 {
bit[++len] = x%base;
x/=base;
}
int ans = 0 , preSum = 0;
for(int i = len ; i > 0 ; i --)
 {
for(int j = 0 ; j < bit[i] && M-preSum-j >= 0 ; j++)
ans += dp[i-1][M-preSum-j];
preSum += bit[i];
}
return ans;
}

int main()
  {
#ifdef ONLINE_JUDGE
#else
freopen("in","r",stdin);
#endif
int Q , X , Y , B , M , K;
int t = 1;
while( ~scanf("%d%d%d%d%d",&Q,&X,&Y,&B,&M) )
 {
printf("Case %d:\n",t++);
init(B,M);
if(X > Y) swap(X,Y); //need !!!!
if(Q==1)printf("%d\n",cal(Y+1,B,M) - cal(X,B,M));
else
 {
scanf("%d",&K);
K += cal(X,B,M);
int low = X , high = Y;
while(high >= low)
 {
int mid = (0LL + high + low )>>1; //exceed int
if(cal(mid+1,B,M)>=K)high = mid - 1;
else low = mid + 1;
}
if(low == Y + 1)puts("Could not find the Number!");
else printf("%d\n",low);
}
}
return 0;
}



|