牛客周赛Round31

A.小红小紫替换

判断即可

$code:$

void solve() {
    std::string s;
    std::cin >> s;   
    std::cout << (s == "kou" ? "yukari" : s) << '\n';
    
}

B.小红的因子数

看到数据范围为 $1e13$,$\sqrt{1e13} \approx 3e6$ 所以直接枚举根号以内的素因子即可

复杂度 $O(\sqrt{n})$

$code:$

void solve() {
    i64 x;
    std::cin >> x;
    
    int ans = 0;
    for(int i = 2; i <= x / i; i ++ ) {
        if(x % i == 0) {
            while(x % i == 0) {
                x /= i;
            }
            ans ++;
        }
    }
    
    ans += x > 1;
    std::cout << ans << '\n';
}

C.小红的字符串中值

首先观察到,中值左右俩边的字符数量一定相等,然后我们只需要枚举$S$中每一个等于询问字符的位置,然后计算左右两边能取到多少即可

void solve() {
    int n;
    char o;
    std::cin >> n >> o;
    
    std::string s;
    std::cin >> s;
    
    i64 ans = 0;
    for(int i = 0; i < n; i ++ ) {
        if(s[i] == o) {
            i64 l = i, r = n - i - 1;
            ans += std::min(l, r) + 1;
        }
    }
    std::cout << ans << '\n';
}

D.小红数组操作

模拟链表即可,每个数维护一个节点,记录左右相连的值,模拟操作

void solve() {
    int q;
    std::cin >> q;
    std::map<int, int> l, r;
    r[0] = -1;
    int siz = 0;
    while(q -- ) {
        int op, x, y;
        std::cin >> op;
        if(op == 1) {
            std::cin >> x >> y;
            r[x] = r[y];
            l[x] = y;
            l[r[y]] = x;
            r[y] = x;
            siz ++;
        } else {
            std::cin >> x;
            r[l[x]] = r[x];
            l[r[x]] = l[x];
            siz --;
        }
    }
    
    std::cout << siz << '\n';
    int now = r[0];
    while(now != -1) {
        std::cout << now << ' ';
        now = r[now];
    }
}

E.小红数组操作

因为数据范围比较小,我们能想到 $dp$,我们定义 $dp_i$ 表示的是所有元素和为 $i$ 时选择的元素数量最小为多少,对于每个数字有选和不选俩种情况,记录选择上一位选完的状态为 $dp$ ,当前位的状态为 $_dp$ ,当前状态能由上一位推出,并且没有影响,我们枚举上一位有的情况,然后对于 $a_i$ 选和不选俩种情况更新 $_dp$,实际上就是滚动数组,也可以记录位置,用二维 $dp$ ,同理 $$ 选:_dp[i - a[pos]] = std::min(_dp[i - a[pos]], dp[i] + 1) \newline 不选:_dp[i + a[pos]] = std::min(_dp[i + a[pos]], dp[i]); \newline 注意:这里如果 _dp 中没有这个元素就直接更新 $$ $code:$

void solve() {
    int n;
    std::cin >> n;
    std::vector<int> a(n);
    for(int i = 0; i < n; i ++ ) {
        std::cin >> a[i];
    }
    
    std::map<int, int> dp;
    dp[0] = 0;
    for(int i = 0; i < n; i ++ ) {
        std::map<int, int> _dp;
        for(auto [v, y] : dp) {
            if(!_dp.count(v - a[i])) {
                _dp[v - a[i]] = y + 1;
            } else {
                _dp[v - a[i]] = std::min(_dp[v - a[i]], y + 1);
            }
            if(!_dp.count(v + a[i])) {
                _dp[v + a[i]] = y;
            } else {
                _dp[v + a[i]] = std::min(_dp[v + a[i]], y);
            }
        }
        dp = _dp;
    }
    std::cout << (dp.count(0) ? dp[0] : -1) << '\n';
}

F.小红的连续段

$code:$

void solve() {
    int x, y;
    std::cin >> x >> y;
    
    static constexpr int P = 1e9 + 7;
    std::vector<i64> fac(1001), invfac(1001), inv(1001);
    fac[0] = invfac[0] = fac[1] = invfac[1] = inv[1] = 1;
    for(int i = 2; i <= 1000; i ++ ) {
        inv[i] = (P - P / i * inv[P % i] % P) % P;
        fac[i] = fac[i - 1] * i % P;
        invfac[i] = invfac[i - 1] * inv[i] % P;
    }
    
    auto C = [&](i64 n, i64 m) -> i64 {
        if(m > n) return 0;
        return fac[n] * invfac[n - m] % P * invfac[m] % P;
    };
    
    std::vector<i64> ans(x + y + 1);
    for(int i = 1; i <= x - 1; i ++ ) {
        ans[2 * i + 1] = (ans[2 * i + 1] + C(x - 1, i) * C(y - 1, i - 1) % P) % P;
    }
    for(int i = 0; i <= x - 1; i ++ ) {
        ans[2 * i + 2] = (ans[2 * i + 2] + C(x - 1, i) * C(y - 1, i) % P) % P;
    }
    
    for(int i = 1; i <= y - 1; i ++ ) {
        ans[2 * i + 1] = (ans[2 * i + 1] + C(y - 1, i) * C(x - 1, i - 1) % P) % P;
    }
    for(int i = 0; i <= x - 1; i ++ ) {
        ans[2 * i + 2] = (ans[2 * i + 2] + C(y - 1, i) * C(x - 1, i) % P) % P;
    }
    
    for(int i = 1; i <= x + y; i ++ ) {
        std::cout << ans[i] << '\n';
    }
}