hdu3555 数位dp 入门

来源:互联网 发布:乐视手机mac码在哪里 编辑:程序博客网 时间:2024/05/02 02:00

飞向题目,biu biu biu
题目大意:给你一个数n,让你求1~n中所有包含49的所有可能。

题目很好理解,就是在做的时候没有思路,看了两篇写得非常好的博客,并且看了半天才看懂。毕竟也是第一道数位dp嘛。

解题思路:设dp大小为dp[20][3] ,因为n的大小为1<=n<=2^63-1;所以最多不超过20位。
dp含义:
dp[i][0] 表示长度为i但不包含49的数据的个数。
dp[i][1] 表示长度为i但不包含49,并且第i位为9的数据的个数。
dp[i][2] 表示长度为i包含49的所有数据的个数。
状态转移:(原因在代码注释里写得很清楚了,我就不再这里罗嗦了)
dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1];
dp[i][1] = dp[i-1][0];
dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1];

看了两篇博客,代码都大同小异,不过都是很优秀的博客。
飞向博客 biu biu biu
第二篇博客 biu biu biu
接下来就是代码了 ps:(这可能是我写得最仔细的一篇博客了)

// DP[i][0] 表示在第i位时,不包含49的数据的个数。// DP[i][1] 表示在第i位时,不包含49,但第i位为9的数据的个数。// DP[i][2] 表示在第i位时,包含49的数据的个数。#include <iostream>#include <algorithm>#include <cstdio>#include <cstring>#define ll long longusing namespace std;ll dp[20][3]; int num[20]; //用来存储n的每一位。int main(){    dp[0][0] = 1;    for (int i = 1;i < 20;++i){        dp[i][0] = dp[i-1][0] * 10 - dp[i-1][1]; //要减去一个第i-1位为9的情况,因为如果第i位为4的话就会构成49。        dp[i][1] = dp[i-1][0]; //只让第i位为9,则就等于1x(以前不包含49的所有情况)。        dp[i][2] = dp[i-1][2] * 10 + dp[i-1][1]; //以前包含的49则第i位有10中可能,加上以前没有包含49但是第i-1位为9的情况。    }    int t;    ll n;    cin >> t;    while(t--){        scanf("%lld",&n);        memset(num,0,sizeof(num));        n++; // 这里加个一是为了防止特殊情况,因为下面写的是num[i] > 4,万一给的数据是49怎么办。所以这里要加一。        int len = 1;        while(n){ // 将n的每一位存储起来。            num[len++] = n % 10;            n /= 10;        }        bool flag = false; //用来标记以前出现过49没有        ll ans = 0,last = 0;        for (int i = len ;i >= 1;--i){ //从高位开始取,这里从len和len-1开始都是一样的。因为都不会改变ans的值            ans += dp[i-1][2] * num[i]; // 加上i-1位所有包含49的情况。第i位可以填1到num[i]的数据。            if (flag == 1){// 如果前面出现了49的情况,则后面的数据可以直接加上了。                ans += dp[i-1][0] * num[i];            }            if (flag == 0 && num[i] > 4){ //如果没有前面没有出现49的情况,并且第i位大于4;                ans += dp[i-1][1];          //则加上第i位为4,第i-1位为9的所有情况            }            if (last == 4 && num[i] == 9){ // 如果出现49的情况则改变标记。                flag = true;            }            last = num[i];        }        printf("%lld\n",ans );    }    return 0;}
0 0