Time Limit: 1000MS | Memory Limit: 65536KB | 64bit IO Format: %I64d & %I64u |
Description
Create a code to determine the amount of integers, lying in the set [
X;
Y] and being a sum of exactly
K different integer degrees of
B.
Example. Let
X=15,
Y=20,
K=2,
B=2. By this example 3 numbers are the sum of exactly two integer degrees of number 2:
17 = 2
4+2
0,
18 = 2 4+2 1,
20 = 2 4+2 2.
18 = 2 4+2 1,
20 = 2 4+2 2.
Input
The first line of input contains integers
X and
Y, separated with a space (1 ≤
X ≤
Y ≤ 2
31−1). The next two lines contain integers
K and
B (1 ≤
K ≤ 20; 2 ≤
B ≤ 10).
Output
Output should contain a single integer — the amount of integers, lying between
X and
Y, being a sum of exactly
K different integer degrees of
B.
Sample Input
input | output |
---|---|
15 20 2 2 | 3 |
Source
Problem Source: Rybinsk State Avia Academy
题意:求一个区间内满足条件的数有多少个,条件是该数可以写成k个b的不同次方的和
题解:建议看一下 刘聪的《浅谈数位类统计问题》那里很详细的写了,如何将该问题化成二进制的问题,然后用数位dp就能解决
//记忆化搜索
#include<stdio.h>
#include<string.h>
int k,b,all,num[108],dp[108][28];
int dfs(int hight,int cou,int limit)
{
int res=0;
if(cou<0) return 0;
if(hight<=0) return cou==0?1:0;
if(!limit&&~dp[hight][cou]) return dp[hight][cou];
if(num[hight]||!limit) res+=dfs(hight-1,cou-1,limit);
res+=dfs(hight-1,cou,limit&&!num[hight]);
if(!limit) dp[hight][cou]=res;
return res;
}
int solve(int n)
{
int i;
for(all=0;n;n=n/b) num[++all]=n%b;
for(i=all;i>=1;i--) if(num[i]>1) break;
for(;i>=1;i--) num[i]=1;
return dfs(all,k,1);
}
int main()
{
int x,y;
memset(dp,-1,sizeof(dp));
while(scanf("%d%d%d%d",&x,&y,&k,&b)>0)
{
printf("%d\n",solve(y)-solve(x-1));
}
return 0;
}
//dp
#include<stdio.h>
#include<string.h>
int x,y,k,b,num[38],dp[38][38];
int solve(int x)
{
int res=0,len,i,cou;
memset(num,0,sizeof(num));
for(len=0;x;x/=b) num[++len]=x%b;
for(i=len;i>=1;i--) if(num[i]>1) break;
for(;i>=1;i--) num[i]=1;
for(cou=0,i=len;i>=1;i--)
{
if(num[i])
{
if(k>=cou) res+=dp[i-1][k-cou];
cou++;
}
}
if(cou==k) res++;
return res;
}
int main()
{
int i,j;
memset(dp,0,sizeof(dp));
for(dp[0][0]=i=1;i<=33;i++)
{
for(j=0;j<=i;j++)
{
dp[i][j]=dp[i-1][j];
if(j-1>=0) dp[i][j]+=dp[i-1][j-1];
}
}
while(scanf("%d%d%d%d",&x,&y,&k,&b)>0)
{
printf("%d\n",solve(y)-solve(x-1));
}
return 0;
}