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);
}
}