• A - Rolling Dice">A - Rolling Dice
  • B - Factorial Yen Coin">B - Factorial Yen Coin
  • C - Fair Candy Distribution">C - Fair Candy Distribution
  • D - Shortest Path Queries 2">D - Shortest Path Queries 2
  • E - Digit Products">E - Digit Products

    比赛链接:Here

    A - Rolling Dice

    水题

    一个六面的骰子,请问摇动 AtCoder Beginner Contest 208 - 图1 次最后的点数和能否为 AtCoder Beginner Contest 208 - 图2

    如果 AtCoder Beginner Contest 208 - 图3 输出 YES

    • C++
    1. void solve() {
    2. int a, b; cin >> a >> b;
    3. if (a * 1 <= b && a * 6 >= b)cout << "Yes\n"; else cout << "No\n";
    4. }
    • Python
    1. A,B = map(int,input().split())
    2. if A <= B <= 6 * A:
    3. print("Yes")
    4. else:
    5. print("No")

    B - Factorial Yen Coin

    找零问题 or 完全背包问题

    • C++
    1. void solve() {
    2. ll n;
    3. cin >> n;
    4. int i = 2, cnt = 0;
    5. while (n) {
    6. cnt += n % i;
    7. n /= i++;
    8. }
    9. cout << cnt << "\n";
    10. }

    另一种写法

    1. int fac(int i) {return i ? fac(i - 1) * i : 1;}
    2. void solve() {
    3. int n;
    4. cin >> n;
    5. int cnt = 0;
    6. for (int i = 1; i <= 10; ++i) {
    7. int div = fac(i + 1);
    8. int res = n % div;
    9. cnt += res / fac(i);
    10. n -= res;
    11. }
    12. cout << cnt << "\n";
    13. }
    • Python
    1. from math import factorial
    2. P = int(input())
    3. answer = 0
    4. for i in range(10, 0, -1):
    5. while factorial(i) <= P:
    6. answer += 1
    7. P -= factorial(i)
    8. print(answer)

    C - Fair Candy Distribution

    构造

    一开始想错了,想模拟写。但在写样例时发现这个是对 k 平均分配,对于排序之后 AtCoder Beginner Contest 208 - 图4 小的需要 + 1

    • C++
    1. void solve() {
    2. int n; ll k; cin >> n >> k;
    3. vector<ll>a(n), b(n);
    4. for (int i = 0; i < n; ++i) cin >> a[i], b[i] = a[i];
    5. sort(a.begin(), a.end());
    6. for (int i = 0; i < n; ++i) {
    7. if (b[i] < a[k % n])cout << k / n + 1 << "\n";
    8. else cout << k / n << "\n";
    9. }
    10. }
    • Python
    1. n, k = map(int, input().split())
    2. A = list(map(int, input().split()))
    3. B = sorted(A)
    4. print(*[k // n + (A[i] < B[k % n]) for i in range(n)])

    D - Shortest Path Queries 2

    最短路问题

    跑 FLoyd 最短路即可

    • C++
    1. const int N = 410, mod = 1e9 + 7;
    2. ll f[N][N];
    3. void solve() {
    4. memset(f, 0x3f, sizeof(f));
    5. ll n, m; cin >> n >> m;
    6. for (int i = 1; i <= n; ++i)f[i][i] = 0;
    7. for (int i = 0, a, b, c; i < m; ++i) {
    8. cin >> a >> b >> c;
    9. f[a][b] = c;
    10. }
    11. ll cnt = 0;
    12. for (int k = 1; k <= n; ++k)
    13. for (int i = 1; i <= n; ++i)
    14. for (int j = 1; j <= n; ++j)
    15. cnt += ((f[i][j] = min(f[i][j], f[i][k] + f[k][j])) != f[0][0]) ? f[i][j] : 0;
    16. cout << cnt << "\n";
    17. }
    • Python (TLE)
    1. import sys
    2. n, m = map(int, sys.stdin.buffer.readline().split())
    3. ABC = map(int, sys.stdin.buffer.read().split())
    4. d = [[1 << 60] * n for i in range(n)]
    5. for i in range(n):
    6. d[i][i] = 0
    7. for a, b, c in zip(ABC, ABC, ABC):
    8. d[a - 1][b - 1] = c
    9. cnt = 0
    10. for k in range(n):
    11. nxt = [[0] * n for i in range(n)]
    12. for i in range(n):
    13. for j in range(n):
    14. nxt[i][j] = min(d[i][j], d[i][k] + d[k][j])
    15. if nxt[i][j] < (1 << 59):
    16. cnt += nxt[i][j]
    17. d = nxt
    18. print(cnt)

    E - Digit Products

    数位 DP ,时间复杂度:AtCoder Beginner Contest 208 - 图5#card=math&code=%5Cmathcal%7BO%7D%28log%5C%20n%29)


    对于这道题来说,如果一个个去构造肯定是是 TLE (AtCoder Beginner Contest 208 - 图6),所以我们利用数位 DP (一种著名的组合算法,用于快速计算受数字约束的、不超过 AtCoder Beginner Contest 208 - 图7 的整数)

    • 构造一个 DP状态:即到目前为止确定的前 i 个数字是否严格小于 AtCoder Beginner Contest 208 - 图8 个数字
    • 状态转移方程:AtCoder Beginner Contest 208 - 图9AtCoder Beginner Contest 208 - 图10 位(AtCoder Beginner Contest 208 - 图11除外)的组合数,其乘积为AtCoder Beginner Contest 208 - 图12
    • 同样,设 AtCoder Beginner Contest 208 - 图13(N的前 AtCoder Beginner Contest 208 - 图14 位的乘积)。
    1. using ll = long long;
    2. unordered_map<ll, ll>f[23];
    3. ll n, k;
    4. vector<int>a;
    5. ll fun(ll x, ll y, ll z, ll t) {
    6. if (!x)return y <= k;
    7. if (!z and !t and f[x][y])return f[x][y];
    8. ll ans = 0;
    9. for (ll i = 0; i <= (z ? a[x - 1] : 9); ++i)
    10. ans += fun(x - 1, y * (!i and t ? 1 : i), z and i == a[x - 1], t and !i);
    11. if (!z and !t)f[x][y] = ans;
    12. return ans;
    13. }
    14. void solve() {
    15. cin >> n >> k;
    16. while (n)a.push_back(n % 10), n /= 10;
    17. cout << fun(a.size(), 1, 1, 1) - 1;
    18. }