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?
The input terminates by end of file marker.
3 1 50 500
0
1
15
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.
T组,每次给一个数n,让求1-n之间有多少个数中含有49。
还是一个模板套下来,不过值得一提的是,这个是第一个完完全全脱了稿做出来的数位dp题目,哈哈,虽然是这个题简单,但是原来这么轻松,真是提自信了。不过没有一A还是很遗憾,没有注意到n的值是2^64-1,第一次用了LL确忘了把n定义成LL,而却dp[]、a[]都开小了点,换大了就好了。
代码如下:
#include <iostream>
#include <cstring>
using namespace std;
typedef long long LL;
LL dp[100][3];
//sta 0: 末尾不是4 1:末尾是4 2: 有49
int a[100];
LL ans;
LL dfs(int pos, int sta, bool limit)
{
if (pos == -1)
{
if (sta == 2)
return 1;
return 0;
}
if (!limit && dp[pos][sta] != -1)
return dp[pos][sta];
int up = limit ? a[pos] : 9;
LL temp = 0;
for (int i = 0; i <= up; i++)
{
int sta2 = sta;
if (sta == 0 && i == 4)//不是4出现4
sta2 = 1;
if (sta == 1)//有4
{
if (i == 4)//又是4
sta2 = 1;
else if (i == 9)//出现49
sta2 = 2;
else//不是49/44,出现4*
sta2 = 0;
}
temp += dfs(pos - 1, sta2, limit && i == a[pos]);
}
if (!limit)
dp[pos][sta] = temp;
return temp;
}
LL solve(LL x)
{
int pos = 0;
while (x)
{
a[pos++] = x % 10;
x /= 10;
}
return dfs(pos - 1, 0, true);
}
int main()
{
int T;
LL n;
memset(dp, -1, sizeof(dp));
cin >> T;
while (T--)
{
cin >> n;
memset(a, 0, sizeof(a));
LL ans = solve(n);
cout << ans << endl;
}
return 0;
}
1438

被折叠的 条评论
为什么被折叠?



