Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 11470 Accepted Submission(s): 4086
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?
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.
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 15HintFrom 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.
题目意思是给定一段区间,求数字中含有49的数的个数。
首先显然需要将这个数按位存储在
建立数组dp[25][3],dp[i][0]表示到第i个位置的没有49的个数
dp[i][1]表示到第i个位置的没有49但是最高位是9的数的个数,像9,90,91,92,93,94,95,96,97,98,99这些都是。之所以统计这一项是因为只要在下一位添加4,就可以组成这些数个49
dp[i][2]表示到第i个位置的含49的数的个数
那么经过预处理以后,我们就可以得到一个位数这三项的个数,然后我们根据所给的数字就可求出对应的49的个数,方法如下:
我们仍从低位向高位进行分析,首先ans加上到第i位含49的数的个数,然后进行分析如果这个数当前位数大于4的话,加上所有该位第一位的dp[i][1]的数目乘以该数,这说明在当前位数的数量级下有的49的个数(因为高位大于了4),最后如果出现49含有的话,每一次除了加上上一位时所有含49的,还需要加上所有不是49的数的个数,因为有了49,高位无论加上什么数他都是含有49的。
代码如下,很好理解:flag表示是否出现了49
/*************************************************************************
> File Name: Bomb.cpp
> Author: Zhanghaoran
> Mail: chilumanxi@xiyoulinux.org
> Created Time: Tue 03 Nov 2015 06:01:49 PM CST
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
using namespace std;
int num[25];
long long dp[25][3];
int T;
long long x;
void init(){
dp[0][0] = 1;
dp[0][1] = 0;
dp[0][2] = 0;
for(int i = 1; i < 25; 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];
}
}
int make_num(long long x){
int len = 0;
while(x){
num[++ len] = x % 10;
x /= 10;
}
num[len + 1] = 0;
return len;
}
int main(void){
scanf("%d", &T);
init();
while(T --){
cin >> x;
int len = make_num(x);
bool flag = false;
long long ans = 0;
for(int i = len; i >= 1; i --){ //1449 -> 9441
ans += num[i] * dp[i - 1][2];
if(flag)
ans += num[i] * dp[i - 1][0];
else{
if(num[i] > 4){
ans += dp[i - 1][1];
}
}
if(num[i + 1] == 4 && num[i] == 9)
flag = true;
}
if(flag){
ans ++;
}
cout << ans << endl;
}
}
有做Beautiful numbers那个题,很自然的想到是否用DFS记忆搜索dp可以做。显然也是没有问题的。
加两个判断条件,一个是判断是否到达上限,一个判断最高位是否是4
代码:
/*************************************************************************
> File Name: Bomb_dfs.cpp
> Author: Zhanghaoran
> Mail: chilumanxi@xiyoulinux.org
> Created Time: Tue 10 Nov 2015 07:43:05 PM CST
************************************************************************/
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
int T;
long long N;
long long dp[25][2];
int num[25];
long long work(int pos, bool fir_4, bool max){
if(pos == 0){
return 0;
}
if(!max && dp[pos][fir_4]){
return dp[pos][fir_4];
}
long long ans = 0;
int flag = max ? num[pos] : 9;
for(int i = 0; i <= flag; i ++){
if(fir_4 && i == 9){
long long di = pow(10, pos - 1);
ans += max ? N % di + 1 : di;
}
else{
ans += work(pos - 1, i == 4, max && num[pos] == i);
}
}
if(!max)
dp[pos][fir_4] = ans;
return ans;
}
long long calc(long long N){
int i = 1;
while(N){
num[i ++] = N % 10;
N /= 10;
}
return work(i - 1, false, true);
}
int main(void){
scanf("%d", &T);
while(T --){
scanf("%lld", &N);
cout << calc(N) << endl;
}
return 0;
}