ural 1057 Amount of Degrees(数位dp)

来源:互联网 发布:偶像梦幻祭卡牌数据 编辑:程序博客网 时间:2024/04/26 10:13

Amount of Degrees
Time Limit: 1000MS Memory Limit: 65536KB 64bit IO Format: %I64d & %I64u

[Submit]   [Go Back]   [Status]  

Description

Create a code to determine the amount of integers, lying in the set [ XY] 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 Input

inputoutput
15 2022
3

Source

Problem Source: Rybinsk State Avia Academy 

[Submit]   [Go Back]   [Status]  


题意:求一个区间内满足条件的数有多少个,条件是该数可以写成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;}


1 0
原创粉丝点击