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 15
Hint
开始看不懂题的时候可以看一下后面的举例子,做题的时候没有看到例子好久才看懂的,说多了都是泪。
题目大意:
给一个数字n,范围在1~2^63-1,求1~n之间含有49的数字有多少个。
经典的数位dp,参考了大腿的代码:http://www.cnblogs.com/luyi0619/archive/2011/04/29/2033117.html
状态转移:
dp[i][0]代表长度为 i 并且不含有49的数字的个数;
dp[i][1]代表长度为 i 并且不含有49,但是最高位是9的数字的个数;
dp[i][2]代表长度为 i 并且含有49的数字的个数。
数组 a[i] 从低位到高位存储 n 的每一位数字。
详解参考:http://www.cnblogs.com/liuxueyang/archive/2013/04/14/3020032.html
代码如下:
#include<iostream> #include <string.h> #include <stdio.h> using namespace std; typedef long long ll; ll dp[25][3]; void init() { dp[0][0] = 1; //表示位数为i的无49的个数; 等于1是为首位为9,位数为1的数服务; dp[0][1] = 0; //表示位数为i的无49的个数但最高位为9的个数; dp[0][2] = 0; //表示位数为i的含有49的个数; for(int i = 1; i < 25; i++) { dp[i][0] = dp[i - 1][0] * 10 - dp[i - 1][1]; //减去最高位为9的情况; dp[i][1] = dp[i - 1][0]; //最高位加9的个数 dp[i][2] = dp[i - 1][2] * 10 + dp[i - 1][1]; //加上没含49但最高位是9的个数(加上4就成49了); } } ll solve(ll n) { ll ans = 0; bool vis = false; int bit[25],tot = 0; while(n) { bit[++tot] = n % 10; n /= 10; } bit[tot + 1] = 0; for(int i = tot; i >= 1; i--) { ans += dp[i - 1][2] * bit[i]; if(vis) ans += bit[i] * dp[i - 1][0]; // 这一步和下一步要细心体会其中的高深之处,看了kuangbin大神的代码好久才明白这个道理; else if(bit[i] > 4) ans += dp[i - 1][1]; //如果n本身已经含有49了就不用考虑是否最高位为9了,直接加上没49的个数,因为n含了49 if(bit[i + 1] == 4 && bit[i] == 9) vis = true; } if(vis) ans++; //如果n本身也包含49,则要加1; return ans; } int main() { ll n; int t; init(); scanf("%d", &t); while(t--) { scanf("%lld",&n); printf("%lld\n",solve(n)); } return 0; }