[2022 HBCPC H] Hamster and Multiplication

https://codeforces.com/gym/103729

题意:
定义 \(f(x)\) 为将 \(x\) 的各个数位乘起来,只剩个位数时返回,求 \(\sum_{i=1}^{n}f(i)\)

思路:
题面就很数位 \(dp\)。注意到每次将数位乘起来下降得很快,并且最后的总结果数也不会太多,所以我们直接记录一路下来的乘积,用一个 map 代替 \(dp\) 数组即可。注意前导 \(0\) 的处理。

好久没写数位 \(dp\) 了,感觉已经不会了QwQ,这么简单的题赛时没开出来真的是乌鱼子。

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;

ll n, dig[23], len;
map< pair<int, ll>, ll> dp;

ll calc(ll m) {
    while (m >= 10) {
        ll x = m, res = 1;
        do {
            res = res * (x % 10);
            x /= 10;
        } while (x);
        m = res;
    }
    return m;
}

ll dfs(int pos, ll mul, bool lim, bool ok) {
    if (!pos) {
        if (ok) return 0;
        return calc(mul);
    }
    if (!lim && !ok && dp.count({pos, mul})) return dp[{pos, mul}];
    int top = lim? dig[pos] : 9;
    ll tmp = 0;
    for (int i = 0; i <= top; ++i) {
        tmp += dfs(pos - 1, mul * (i == 0? ok : i), lim && (i == top), ok && !i);
    }
    if (!lim && !ok) dp[{pos, mul}] = tmp;
    return tmp;
}

void solve() {
    cin >> n;
    ll x = n;
    do {
        dig[++len] = x % 10;
        x /= 10;
    } while(x);
    cout << dfs(len, 1, true, true) << '\n';
}

int main() {
#ifndef stff577
    ios::sync_with_stdio(false);
    cin.tie(nullptr);cout.tie(nullptr);
    cout << fixed << setprecision(20);
#endif
    int t = 1;
    while (t--) solve();
    return 0;
}
posted @ 2022-06-09 10:51  stff577  阅读(454)  评论(3编辑  收藏  举报