HDU4734 F(x)[数位DP]

来源:互联网 发布:profili软件介绍 编辑:程序博客网 时间:2024/05/21 13:22

D - F(x)

 HDU - 4734 






题意:

求出存在[0,B]中x使得F(x)小于等于F(A)的数有多少个。


题解:

首先求出F(A)的值,用这个值作为标记的初始值,第一维代表当前位置,第二维代表剩余值。而第二维的取值,最多能达到9*9*2^8,计算过程中,如果sum小于0,代表不可能因为要保证必须比F(A)小,直接返回0,而减的过程中,直接用i*(i<<pos) (pos为当前位置,i为当前取值),这题不需要理会前导零的问题。

状态转移的话,dp[i][j] 第一维表示当前位置,第二维表示剩余的值(即当前位置往后计算的过程中不能超过的值)。


#pragma comment(linker, "/STACK:102400000,102400000")#include<iostream>#include<cstdio>#include<cstring>#include<cmath>#include<string>#include<algorithm>#include<queue>#include<stack>#include<set>#include<map>#include<vector>using namespace std;typedef long long ll;const int N=2e4+1e3;//9*9*2^8const int M=10;int num[M];int dp[M][N];int dfs(int pos,int sum,bool limit){    if (pos==-1)        return sum>=0;    if (sum<0)        return 0;    if (!limit && dp[pos][sum]!=-1)        return dp[pos][sum];    int cnt=0;    int mx=limit?num[pos]:9;    for (int i=0 ; i<=mx ; ++i)        cnt+=dfs(pos-1,sum-i*(1<<pos),limit && i==num[pos]);    if (!limit)        dp[pos][sum]=cnt;    return cnt;}int f(int x){    int sum=0,two=1;    while (x)    {        sum+=(x%10)*two;        x/=10;        two*=2;    }    return sum;}int solve(int a,int b){    int pos=0;    while (b)    {        num[pos++]=b%10;        b/=10;    }    return dfs(pos-1,f(a),1);}int main(){    int T;    scanf("%d",&T);    memset(dp,-1,sizeof(dp));    for (int test=1 ; test<=T ; ++test)    {        int a,b;        scanf("%d%d",&a,&b);        printf("Case #%d: %d\n",test,solve(a,b));    }    return 0;}


原创粉丝点击