Atcoder Beginner Contest 154 E-F 题解

Atcoder Beginner Contest 154 E-F 题解


E - Almost Everywhere Zero

Atcoder Beginner Contest 154 E-F 题解_第1张图片
解法:简单的数位dp

  1. f 为是否在判前导0,g 为是否在卡上界
  2. num=0 时刚好有 k 个不为0 的数位
ll dp[110][4][2][2];
// f 为是否在判前导0,g 为是否在卡上界
ll dfs(int cur, int num, bool f, bool g) {
    //cout << "xxx " << cur << ' ' << num << ' ' << f << ' ' << g << '\n';
    if (num < 0) return 0;
    if (dp[cur][num][f][g] != -1) return dp[cur][num][f][g];
    if (cur == str.size()) {
        // num=0 时刚好有 k 个不为0 的数位
        if (num == 0) return 1;
        else return 0;
    }
    ll res = 0;
    int x = !g ? 9 : str[cur] - '0';
    ll ans = 0;
    //cout << x << '\n';
    for (int i = 0;i <= x;i++) {
        if (i == 0) ans += dfs(cur + 1, num, f & (i == 0), g & (i == x));
        else ans += dfs(cur + 1, num - 1, f & (i == 0), g & (i == x));
    }
    return dp[cur][num][f][g] = ans;
}

void solve() {
    cin >> str >> k;
    memset(dp, -1, sizeof(dp));
    cout << dfs(0, k, 1, 1) << '\n';
}



F -Many Many Paths (NTT做法)

Atcoder Beginner Contest 154 E-F 题解_第2张图片

数据范围:1e6 + 1e6

解法:

  1. 可以用 ntt 强凹, 但因为我不知道 1e9+7 的ntt, 所以用的任意模数 ntt 的板子。

  2. C(x+y,x) = (x+y)! / x! / y! , 则可转化为 指数型生成函数,相乘,最后将得到的每个位乘以 i! 加起来就完了。

  3. 代码块

    // 记得此处是任意模数 ntt 的板子
    // 可以在洛谷找一个
    n = m = 1e6 + 10;
    int lx = read(), ly = read(), rx = read(), ry = read();
    for (int i = lx;i <= rx;i++) A[i] = Int(invfac[i]);
    for (int i = ly;i <= ry;i++) B[i] = Int(invfac[i]);
    Poly::init(n + m);
    Poly::NTT(A), Poly::NTT(B);
    for (int i = 0; i < Poly::lim; ++i) A[i] = A[i] * B[i];
    Poly::NTT(A, 0);
    ll res = 0;
    for (int i = 0; i < n + m - 1; ++i) res = (res + fac[i] * A[i].get() % mod) % mod;
    printf("%lld\n", res);
    

你可能感兴趣的:(Atcoder,算法,c++,开发语言)