Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 7781 Accepted Submission(s): 2726
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.
Author
fatboy_cw@WHU
Source
Recommend
题目大意:给你一个数n叫你求出求出1到n中含有49的数的个数,如500里面有
"49","149","249","349","449","490","491","492","493","494","495","496","497","498","499",这16个
思路:
这是做的
第一道数位dp的题目,我对数位dp的理解就是对数的每一位只取到该位的整数位(例如4444的话当对第四位进行数位dp时只取到0到4000的数,接着对第三位进行数位dp,这时数位dp的范围是4000到4400的数,所以保证不会有重复,往后依次类推)
数位dp,先预处理一遍,
dp[i][0]代表该位为9的所有不合法的状态,
dp[i][1]代表该位不合法的所有状态,
dp[i][2]代表该位合法的所有状态.然后先预处理
预处理9,99,999...,9999999999..的所有dp[i][j]的情况.dp[i][0] 必须是
该位为9的所有不合法的状态,不然的话会有重复的情况如(99999 对第5位进行dp时,这时ans+=dp[i-1][2] + dp[i-1][0],其中dp[i-1][0]的意思是当前位为0下一位为9的情况,如果dp[i][0]代表该位为9的所有状态,那么49490肯定会重复计算,因为49490也被包括在了dp[i-1][2]里面了)
代码:
#include <cstdio>
#include <cmath>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#include <iostream>
#include <queue>
typedef __int64 LL;
using namespace std;
LL dp[100][3];
//dp[i][0]代表该位为9的所有不合法的状态
//dp[i][1]代表该位不合法的所有状态
//dp[i][2]代表该位合法的所有状态
LL n;
void f()
{
int i;
dp[1][0] = 1;
dp[1][1] = 10;
dp[1][2] = 0;
dp[0][1] = 1;
for(i = 2; i <=25; i++)
{
dp[i][0] = dp[i-1][1] ;
dp[i][2] = dp[i-1][0]+ 10*dp[i - 1][2];
dp[i][1] = 10*(dp[i-1][1]) - dp[i-1][0];
}
}
LL ff()
{
LL a[30];
LL k = n;
int len = 1;
while (k > 0)
{
a[len++] = k % 10;
k /= 10;
}
//cout<<len<<endl;
int i;
int vis = 0;
LL ans = 0;
for(i = len - 1; i >= 1; i--)
{
LL m = a[i];
ans += m * dp[i-1][2];
if(vis == 1)
{
ans+= m * (dp[i-1][1]);
//因为数位dp的过程中每次都是以上一个数的最大数作为前缀,所以当该数中某两位
//相邻的出现了49那么接下来的数不管是什么肯定都是合法的。
}
else if(m > 4)
{
ans += dp[i-1][0];
}
if(i!=len&& a[i] == 9 && a[i + 1] == 4)
vis = 1;
}
return ans + vis;
}
int main()
{
int t;
f();
/*int i;
for(i = 1 ;i <=18; i++)
cout<<dp[i][0]<<" "<<dp[i][1]<<" "<<dp[i][2]<<endl;*/
cin>>t;
while(t--)
{
cin>>n;
LL ans = ff();
cout<<ans<<endl;
}
return 0;
}