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;
}

浙公网安备 33010602011771号