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