[数位DP] HDU4734 F(x)

来源:互联网 发布:sqlserver enterprise 编辑:程序博客网 时间:2024/06/05 06:44

HDU4734

题意:设整数x的十进制表示为An*10^n-1 + An-1*10^n-2 ... A1*10^0, 定义函数F(x)=An*2^n-1 + An-1*2^n-2 +...+A1*10^0,然后对任意x∈[0, B]求F(x)值不超过F(A)的x的个数。

解法:数位DP。 DP[i][j]表示1~i位的数中F函数值不超过j的数的个数,DP[len][F(A)]即为答案。

技巧:从F(A)往0搜,如果从0往F(A)搜的话,对不同F(A),DP需要记忆的信息是不同的,每次都重新跑DP会超时。

#include<bits/stdc++.h>#define ll long long intusing namespace std;int f(ll x){    ll res = 0, b = 1;    while(x){        res += (x%10)*b;        x /= 10;        b *= 2;    }    return res;}int dp[15][6000], p2[15];int num[15];int dfs(int pos, int sum, int f){    if(sum < 0) return 0;    if(pos < 1) return sum >= 0;    if(!f && dp[pos][sum] != -1) return dp[pos][sum];    int end = f? num[pos] : 9;    int res = 0;    for(int i = 0; i <= end; ++i){        res += dfs(pos-1, sum-i*p2[pos], f && i == end);    }    if(!f) dp[pos][sum] = res;    return res;}int solve(int a, int b){    int len = 0;    while(b){        num[++len] = b%10;        b /= 10;    }    return dfs(len, f(a), 1);}void init(){    p2[1] = 1;    for(int i = 2; i <= 10; ++i) p2[i] = p2[i-1]*2;    memset(dp, -1, sizeof(dp));}int main(){    init();    int T, ca = 1;    scanf("%d", &T);    while(T--){        int a, b;        scanf("%d%d", &a, &b);        printf("Case #%d: %d\n", ca++, solve(a, b));    }}

0 0
原创粉丝点击