您的位置:首页 > 其它

HDU - 3555 Bomb(数位dp)

2016-07-20 17:09 323 查看

题目链接:

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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  acm