HDU - 3555 Bomb(数位dp)

来源:互联网 发布:异地淘宝客服招聘 编辑:程序博客网 时间:2024/06/07 14:47

题目链接:

http://acm.hdu.edu.cn/showproblem.php?pid=3555

题解:

开一个dp数组,i代表当前数字的长度,dp[i][0]表示不含49的数字个数,dp[i][1]表示最高位为9且不含49的数字的个数,dp[i][2]表示满足条件的数字个数。可以推出以下的递推公式:

dp[0][0] = 1;for(int i = 1; i <= 22; i++){    dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1];//不含49的数字个数    dp[i][1] = dp[i-1][0];//不含49 && 最高位为9的数字个数    dp[i][2] = dp[i-1][1] + dp[i-1][2] * 10;//满足条件的数字个数}

然后讲数字按位输入到数组里,flag代表高位有没有出现过49。首先加上a[i] * i-1位中满足条件的数的个数,如果高位出现过49,加上a[i] * i-1位中不满足条件的数的个数,如果高位没有出现过49, 且第i位 > 4,则加上剩下i-1位中以9开头的数的个数。最后判断高一位和本位是否构成49,更新flag。
注意这种处理需要将n+1,因为处理的是【1, n)的情况,并且需要将最高位的高一位位数表示为0。

AC代码:

#include <iostream>#include <cstdio>#include <algorithm>#include <string>#include <cstring>#include <sstream>using namespace std;long long int N;int number[30];long long int dp[25][3];int main(){    dp[0][0] = 1;    for(int i = 1; i <= 22; i++)    {        dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1];//不含49的数字个数        dp[i][1] = dp[i-1][0];//不含49 && 最高位为9的数字个数        dp[i][2] = dp[i-1][1] + dp[i-1][2] * 10;//满足条件的数字个数    }    int T;    scanf("%d", &T);    while(T--)    {        cin >> N;        N++;//将N加一        bool flag = false;        long long int ans = 0;        int len = 0;        memset(number,0,sizeof(number));        while(N != 0)        {            number[++ len ] = N%10;            N /= 10;        }        number[len + 1] = 0;//将高一位表示为0        for(int i = len; i > 0; i--)        {            ans += number[i] * dp[i-1][2];            if(flag)                ans += dp[i-1][0] * number[i];            if(number[i] > 4 && !flag)                ans += dp[i-1][1];            if(number[i+1] == 4 && number[i] == 9)                flag = true;        }        cout << ans <<endl;    }    return 0;}
0 0
原创粉丝点击