[HDU3555] Bomb 数位DP

Problem Description

The counter-terrorists found a time bomb in the dust.
But this time the terrorists improve on the time bomb. The number sequence of
the time bomb counts from 1 to N. If the current number sequence includes the
sub-sequence "49", the power of the blast would add one point.
Now the
counter-terrorist knows the number N. They want to know the final points of the
power. Can you help them?

Input

The first line of input consists of an integer T (1
<= T <= 10000), indicating the number of test cases. For each test case,
there will be an integer N (1 <= N <= 2^63-1) as the
description.
The input terminates by end of file marker.

Output

For each test case, output an integer indicating the
final points of the power.

Sample Input

3 1 50 500

Sample Output

0 1 15 *Hint*From 1 to 500, the numbers that include the sub-sequence "49" are "49","149","249","349","449","490","491","492","493","494","495","496","497","498","499", so the answer is 15.

Author

fatboy_cw@WHU

Source

2010 ACM-ICPC Multi-University Training Contest(12)——Host by WHU

Recommend

zhouzeyong | We have carefully selected several
similar problems for you: 3554 3556 3557 3558 3559


题解

数位DP

\(f[i][j][0/1]\)\(i\)位数,最高位为\(j\),是否包含数位串‘ 49’ 的数的个数。

预处理\(f\)数组后进行数位DP。

先填充位数不满的,再由高位向低位将此位不满的加入答案。

统计每一位时考虑先前的位置是否已经出现 ‘49’

转换询问区间为\([1,n)\)则更易简单处理。

code

#include <iostream>
#include <cstdio>
using namespace std;
typedef unsigned long long ULL;
ULL f[50][50][5], bit[50], t, n;
void init() {
    f[0][0][0] = 1; bit[0] = 1;
    for(int i = 1;i <= 20;i ++) {
        bit[i] = bit[i-1] * 10;
        for(int j = 0;j <= 9;j ++) {
            for(int k = 0;k <= 9;k ++) {
                f[i][j][0||(j == 4&&k == 9)] += f[i-1][k][0];
                f[i][j][1||(j == 4&&k == 9)] += f[i-1][k][1];
            }
        }
    }
}
ULL calc(ULL x) {
    int pos, last = 0, flag = 0, di = 1;
    ULL res = 0;
    for(pos = 1;bit[pos] <= x;pos ++) {
        for(int j = 1;j <= 9;j ++) {
            res += f[pos][j][1];
        }
    }
    for( ; pos ;pos --) {
        int now = (x / bit[pos-1]) % 10;
        for(int j = di;j < now;j ++) {
            res += f[pos][j][1] + f[pos][j][0] * flag;
        }
        if(last == 4&&now == 9) flag = 1;
        last = now; di = 0;
    }
    return res;
}
int main() {
    init();
    cin >> t;
    while(t --> 0) cin >> n, cout << calc(n + 1) << endl;
    return 0;
}
posted @ 2019-08-13 06:20  Paranoid丶离殇  阅读(123)  评论(0编辑  收藏  举报