• Divide by Zero 2021 and Codeforces Round #714 (Div. 2) 个人补题记录


    补题链接:Here

    A. Array and Peaks

    题意:给定 数组大小 (n) 和 峰值点 (k) 请问是否存在这样的排序,不存在则输出-1

    先序从 i = 2 开始填,依次 i += 2 ,如果这样还有不够即 (k e 0) 则肯定不存在这种排序。

    接下来就是填空位了

    AC 代码:

    void solve() {
        int n, k;
        cin >> n >> k;
        vector<int> a(n + 1);
        int nn = n;
        for (int i = 2; i <= n; i += 2) {
            if (k == 0) break;
            a[i] = nn--, k--;
        }
        if (k) {
            cout << -1 << "
    ";
            return;
        }
        int cur = 1;
        for (int i = 1; i <= n; ++i)
            if (!a[i]) a[i] = cur++;
        for (int i = 1; i <= n; ++i) cout << a[i] << " ";
        cout << "
    ";
    }
    

    B. AND Sequences

    这道题,仍是看了题解都没怎么理解是这样子做的

    using ll     = long long;
    const ll mod = 1e9 + 7;
    void solve() {
        int n;
        cin >> n;
        vector<int> a(n);
        for (int &x : a) cin >> x;
        int h = 0;
        for (int i = 0; i < 30; ++i) {
            h |= 1 << i;
            for (int x : a)
                if (not((x >> i) & 1)) h &= ~(1 << i);
        }
        int c  = count(a.begin(), a.end(), h);
        ll ans = (ll)c * (c - 1) % mod;
        for (int i = 1; i <= n - 2; ++i) ans = ans * i % mod;
        cout << ans << '
    ';
    }
    

    C. Add One

    题意很容易懂:现给一个大数 (n)(m) 次操作机会,每次操作都要使 (n) 的每个位数 + 1,满十进一。如:(1912 o21023)

    思路:

    由于 (m) 的范围在 ([1,2e5]) 就别想着暴力了,尝试 DP + 预处理

    预处理部分: $DP_{(i,j)} $ 代表第 i 次操作时位数值时 j 的变化值

    [init:dp[0][i] = 1\ dp(i,j) = j < 9 ? dp(i - 1,j + 1) : (dp(i-1,0) + dp(i - 1,1) \% mod) ]

    int M = 2e5 + 10;
    vector<vector<int>> dp(M + 1, vector<int>(10));
    void init() {
        for (int i = 0; i < 10; ++i) dp[0][i] = 1;
        for (int i = 1; i <= M; ++i)
            for (int j = 0; j < 10; ++j) {
                if (j < 9) dp[i][j] = dp[i - 1][j + 1];
                else
                    dp[i][j] = (dp[i - 1][0] + dp[i - 1][1]) % mod;
            }
    }
    

    所以根据 DP 数组,可以快速得到输入值 n,m的情况下最后的位数

    void solve() {
        string s;
        int m;
        cin >> s >> m;
        ll ans = 0;
        for (char c : s) ans = (ans + dp[m][c - '0']) % mod;
        cout << ans << "
    ";
    }
    

    赛后看了下官方题解,发现可以把二维DP压缩为一位DP

    (dp_i) 定义为对数字 (10) 进行 (i) 次运算以后的字符串长度

    • (dp_i = 2,∀ i) in ([0,8])

    • (dp_i = 3,) if (i = 9)

      即对数字 (10) 进行 (9) 次运算后最终数字为 (109)

    • 对于其他情况:(dp_i = dp_{i-9} + dp_{i - 10})

      长度是 (i - 9) 次运算和 (i - 10) 次运算的和

    这里同样先预处理

    最后的答案为 (ans = sum_{i = 1}^{|s|}((m + (int)(s[i] - '0') < 10)?1:dp_{m-10+(int)(s[i] - '0')}))

    • 时间复杂度为:(mathcal{O}(m+t·|s|))
    #define int long long
    const int max_n = 200005, mod = 1000000007;
    int dp[max_n];
    signed main() {
        for (int i = 0; i < 9; i++) dp[i] = 2;
        dp[9] = 3;
        for (int i = 10; i < max_n; i++) {
            dp[i] = (dp[i - 9] + dp[i - 10]) % mod;
        }
        ios_base::sync_with_stdio(false), cin.tie(NULL);
        int t;
        cin >> t;
        while (t--) {
            int n, m;
            cin >> n >> m;
            int ans = 0;
            while (n > 0) {
                int x = n % 10;
                ans += ((m + x < 10) ? 1 : dp[m + x — 10]);
                ans %= mod;
                n /= 10;
            }
            cout << ans << "
    ";
        }
        return 0;
    }
    

    The desire of his soul is the prophecy of his fate
    你灵魂的欲望,是你命运的先知。

  • 相关阅读:
    2级联动下拉列表写法
    select选中获取索引三种写法
    判断设备-安卓|苹果|微信
    限制输入字符个数的jq插件
    面试题:1.清空字符串前后的空格;2.找出出现最多的字符
    css3玩转各种效果【资源】
    利用jquery.touchSwipe.js实现的移动滑屏效果。
    【leetcode刷题笔记】Letter Combinations of a Phone Number
    【leetcode刷题笔记】Linked List Cycle
    【leetcode刷题笔记】Length of Last Word
  • 原文地址:https://www.cnblogs.com/RioTian/p/14649762.html
Copyright © 2020-2023  润新知