1057. Amount of Degrees
Time limit: 1.0 second
Memory limit: 64 MB
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. 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
|
题目大意:
求区间【X,Y】中有几个数,使得其B进制表示中只有0和1并且其中1的个数正好为K个。
思路:
考虑到数位统计,考虑数位Dp.
设定Dp【i】【j】表示B进制表示下,到了第i位,一共有了j个1的可行方案数。
那么对应很好写出状态转移方程:
Dp【i】【j】=Dp【i+1】【j】+Dp【i+1】【j+1】
我们这里记忆化写出来的,我们注意limit的界限和1的情况即可。
Ac代码:
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
int cnt;
int L,R,B,K;
int num[55];
int dp[200][200];
void init(int dig,int jinzhi)
{
while(dig)
{
num[++cnt]=dig%jinzhi;
dig/=jinzhi;
}
reverse(num+1,num+1+cnt);
}
int Dfs(int i,int j,int limit)
{
if(j>K)return 0;
if(i==cnt)
{
if(j==K)
{
dp[i][j]=1;
return dp[i][j];
}
else return 0;
}
if(limit==0&&dp[i][j]!=-1)return dp[i][j];
dp[i][j]=0;
if(limit==0)
{
if(i==0)
{
dp[i][j]+=Dfs(i+1,j,limit);
if(num[1]==1)
dp[i][j]+=Dfs(i+1,j+1,1);
else
{
dp[i][j]+=Dfs(i+1,j+1,limit);
}
return dp[i][j];
}
dp[i][j]+=Dfs(i+1,j,limit);
dp[i][j]+=Dfs(i+1,j+1,limit);
return dp[i][j];
}
else if(limit==1)
{
for(int nex=0;nex<=1&&nex<=num[i+1];nex++)
{
int tmp=j;
if(nex==1)tmp=j+1;
if(nex==num[i+1])
{
dp[i][j]+=Dfs(i+1,tmp,1);
}
else
{
dp[i][j]+=Dfs(i+1,tmp,0);
}
}
return dp[i][j];
}
}
int main()
{
while(~scanf("%d%d%d%d",&L,&R,&K,&B))
{
cnt=0;
memset(dp,-1,sizeof(dp));
init(R,B);
Dfs(0,0,0);
int ans=dp[0][0];
if(L==1)
{
printf("%d\n",ans);
continue;
}
cnt=0;
memset(dp,-1,sizeof(dp));
init(L-1,B);
Dfs(0,0,0);
printf("%d\n",ans-dp[0][0]);
}
}