1043 幸运号码 数位DP

Posted stupid_one

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1043 幸运号码 数位DP相关的知识,希望对你有一定的参考价值。

http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1043

设dp[i][j]表示前i位数中,i位数的和为j时的所有情况。

转移的时候和普通的数位dp是一样转移的,但是如果你压缩了空间的话,就是用滚动数组的话,记录情况数就要多开一个变量来保存,

 

然后看看怎么排除前导0的情况。

如果产生的和值是j,然后前i - 1位产生的和值也是j,那么第i为就是前导0了。需要排除。

然后前n部分的和值的所有情况(需要排除前导0) * 后n部分的和值情况。就是答案。

 

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <assert.h>
#define ios ios::sync_with_stdio(false)
using namespace std;
#define inf (0x3f3f3f3f)
typedef long long int LL;


#include <iostream>
#include <sstream>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <bitset>
const int MOD = 1e9 + 7;
LL dp[2][9 * 1000 + 20];
void work() {
    int n;
    cin >> n;
    dp[0][0] = 1;
    int now = 0;
    for (int i = 1; i <= n; ++i) {
        now = !now;
        for (int k = 0; k <= 9 * i; ++k) {
            LL sum = 0;
            for (int j = 0; j <= 9; ++j) {
                if (k >= j) {
                    sum += dp[!now][k - j];
                    if (sum >= MOD) sum %= MOD;
                }
            }
            dp[now][k] = sum;
        }
    }
    LL ans = 0;
    for (int i = 1; i <= 9 * n; ++i) {
//        assert(dp[now][i] - dp[!now][i] >= 0);
        ans += ((dp[now][i] - dp[!now][i] + MOD) % MOD * dp[now][i]) % MOD;
        if (ans >= MOD) ans %= MOD;
    }
    cout << ans << endl;
}

int main() {
#ifdef local
    freopen("data.txt", "r", stdin);
//    freopen("data.txt", "w", stdout);
#endif
    work();
    return 0;
}
View Code

 

以上是关于1043 幸运号码 数位DP的主要内容,如果未能解决你的问题,请参考以下文章

51nod1043 幸运号码(数位dp)

1043 幸运号码 数位DP

51nod 1043 幸运号码(数位dp)

AC日记——幸运号码 51nod 1043

51Nod_1043_幸运号码

1043 幸运号码