abc208

A - Rolling Dice 28
投 n 次骰子,总点数有没有可能是 k ?

B - Factorial Yen Coin 51
好题,值得知道的贪心
面值为 \(1!,2!,3!,4!,5!,\cdots\) 的纸币各 \(100\) 张,问凑出 \(n(n\le 1e7)\) 块钱(不找零)至少要多少张

从大到小贪心即可,因为任何一个数都有唯一的 “阶乘进制” 表示

考虑十进制,为什么十进制能表示所有数?比如当百位 +1 而使值增加 100 时,右边的所有低位可以通过变化 “覆盖” +0 到 +99

C - Fair Candy Distribution 142

k 个糖发给 n 个人,每个人有两两不同的值 \(a_i\)。当 k>=n 时给每个人发一个糖,不够发时给 \(a_i\) 值前 k 小的人发,发完为止。问最后每个人得几个糖

D - Shortest Path Queries 2 1190

给定点数 400 的图,求所有 \(f(s,t,k)\),即从 s 走到 t,只能经过前 k 个点及 s、t 两点 的最短路长度

floyd最短路板子。有一点要注意(其实好像也不需要很注意):floyd 外层循环到 k 时 s->t 的最短路长度的含义正是本题的定义,即 “只能经过前 k 个点及 s、t 两点”。不需要把给定的边按端点序号排序然后循环的时候依次加入啥的。反正就写个普通的 floyd 就行

E - Digit Products 2024

\([1,n]\) 中数位积不超过 \(K\) 的数有几个?

我的数位dp一直很有问题,为了做这题又重新学了一下,感觉(dls的?)记忆化搜索写法比yxc的好写很多(呃呃

写成记忆化搜索的话,真的就是很简单的数位dp。很多东西都不用计算,无脑循环当前位的取值x,剩下的交给记忆化魔法就行了!

#include <bits/stdc++.h>
using namespace std;
using ll = long long;

ll n, K;
vector<int> num;

map<ll, ll> f[20][2][2];
 //当前位,之前是不是已经小于,前面是不是全是0,当前乘积
ll dfs(int i, bool les, bool zero, ll prod) { //注意中途乘积>K不能直接寄,因为后面还有机会乘0
    if (i == -1) return prod <= K; //算完了
    if (zero) prod = 1; //前面都是0,不能算入乘积
    ll &ans = f[i][les][zero][prod];
    if (ans) return ans;
    for (int x = 0; x <= (les ? 9 : num[i]); x++) {
        ans += dfs(i - 1, les | (x < num[i]), zero && !x, prod * x);
    }
    return ans;
}

int main() {
    cin >> n >> K;
    while (n) num.push_back(n % 10), n /= 10;
    cout << dfs(num.size() - 1, false, true, 1) - 1; //0不算
    
    return 0;
}

posted @ 2023-09-27 21:24  Bellala  阅读(58)  评论(0)    收藏  举报