题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3555
Bomb
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 131072/65536 K (Java/Others)Total Submission(s): 18739 Accepted Submission(s): 6929
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 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.
题解:
数位DP通用:dp[pos][sta1][sta2][……]
表示:当前位为pos,之前的状态为sta1*sta2*……stan。n为限制条件的个数。
回到此题,限制条件有两个: 1.上一位是否为4; 2.之前是否已经出现49。
类似题目:http://blog.youkuaiyun.com/dolfamingo/article/details/72848001
代码如下:
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <vector>
#include <cmath>
#include <queue>
#include <stack>
#include <map>
#include <string>
#include <set>
#define ms(a,b) memset((a),(b),sizeof((a)))
//#define LOCAL
using namespace std;
typedef long long LL;
const int INF = 2e9;
const LL LNF = 9e18;
const int mod = 1e9+7;
const int maxn = 100+10;
LL n;
LL a[maxn], dp[maxn][2][2];
LL dfs(int pos, bool is4, bool lim, bool hav)
{
if(!pos) return hav;
if(!lim && dp[pos][is4][hav]!=-1) return dp[pos][is4][hav];
LL ret = 0;
int m = lim?a[pos]:9;
for(int i = 0; i<=m; i++)
{
bool B = is4&&(i==9);
ret += dfs(pos-1, i==4, lim&&(i==m), B||hav);
}
if(!lim) dp[pos][is4][hav] = ret;
return ret;
}
int main()
{
#ifdef LOCAL
freopen("123", "r", stdin);
// freopen("output.txt", "w", stdout);
#endif
int T;
scanf("%d",&T);
while(T--)
{
scanf("%lld",&n);
int p = 0;
while(n)
{
a[++p] = n%10;
n /= 10;
}
ms(dp,-1);
LL ans = dfs(p, 0, 1, 0);
printf("%lld\n",ans);
}
}
1011



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



