hdu 3555 数位DP

这题完全是看解题报告做出来的,之前完全没有这样的思路, DP数组的含义还是挺好理解的,后面使用的时候反而是想了好久才理解……

/*
* hdu3555/linux.cpp
* Created on: 2011-8-30
* Author : ben
*/
#include
<cstdio>
#include
<cstdlib>
#include
<cstring>
#include
<cmath>
#include
<algorithm>
using namespace std;

typedef
long long I64;
typedef unsigned
long long U64;

/*
* dp[i][0]表示长度为i,不包含49的数字的个数
* dp[i][1]表示长度为i,不包含49但以9开头的数字的个数
* dp[i][2]表示长度为i,包含49的数字的个数
*/
U64 dp[
21][3];
char digit[25];

void work();
int main() {
#ifndef ONLINE_JUDGE
freopen(
"data.in", "r", stdin);
#endif
work();
return 0;
}

void init() {
dp[
0][0] = 1;
dp[
0][1] = 0;
dp[
0][2] = 0;
for(int i = 1; i < 20; i++) {
dp[i][
0] = dp[i - 1][0] * 10 - dp[i - 1][1];
dp[i][
1] = dp[i - 1][0];
dp[i][
2] = dp[i - 1][2] * 10 + dp[i - 1][1];
}
}

void work() {
int T, len;
U64 N, ans;
bool flag;
init();
scanf(
"%d", &T);
while(T--) {
scanf(
"%I64u", &N);
N
++;//加1便于处理形如..49的数
sprintf(digit, "%I64d", N);
len
= strlen(digit);
ans
= 0;
flag
= false;
for(int i = len; i > 0; i--) {
ans
+= dp[i - 1][2] * (digit[len - i] - '0');
if(flag) {
ans
+= dp[i - 1][0] * (digit[len - i] - '0');
}
else {
if(digit[len - i] > '4') {
ans
+= dp[i - 1][1];
}
}
if(i < len && digit[len - i - 1] == '4' && digit[len - i] == '9') {
flag
= true;
}
}
printf(
"%I64u\n", ans);
}
}
posted @ 2011-08-30 16:25  moonbay  阅读(193)  评论(0编辑  收藏  举报