您的位置:首页 > 其它

Hdu 2089 不要62 (数位dp入门题目)

2015-10-28 16:01 369 查看
题目链接:

  Hdu 2089 不要62

题目描述:

  给一个区间 [L, R] ,问区间内不含有4和62的数字有多少个?

解题思路:

  以前也做过这个题目,但是空间复杂度是n。如果数据范围太大就GG了。今天看了一下数位DP,的确有时间和空间上的优越性。
  用数位dp做这个题目的时候,首先要预处理出dp[x][y],代表以y开头的x位数中不含有62和4的数有多少个,在满足条件的情况下状态转移为:dp[x][y] += dp[x-1][k]。又因为对于一个数字x,如果和它位数相同的数字y小于x,那么只需要y数字其中任意一位小于x即可。然后问题就变为求ans([1, r+1]) - ans([1, l])。

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;

const int maxn = 10;
int dp[maxn][maxn];
//dp[x][y] 以y开头的x位数满足题意的个数

void init ()
{
memset(dp, 0, sizeof(dp));
dp[0][0] = 1;
for (int i=1; i<=7; i++)//i位数
for (int j=0; j<10; j++)//第i位数
for (int k=0; k<10; k++)//第i-1位数
{
if(j==4 || j==6&&k==2)
continue ;
dp[i][j] += dp[i-1][k];
}
}

int solve (int n)
{
int a[maxn], len = 0, ans = 0;
while (n)
{
a[++len] = n % 10;
n /= 10;
}
a[len+1] = 0;

for (int i=len; i>0; i--)
{//枚举后len位的策略
for (int j=0; j<a[i]; j++)
{
if (j==4 || a[i+1]==6&&j==2)
continue ;
ans += dp[i][j];
}

if (a[i]==4 || a[i+1]==6 && a[i]==2)
break;
}
return ans;
}

int main ()
{
int n, m;
init ();

while (scanf ("%d %d", &n, &m), n + m)
printf ("%d\n", solve(m+1) - solve(n));
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: