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

补题链接:Here

A. Array and Peaks

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

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

接下来就是填空位了

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 << "\n";
        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 << "\n";
}

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 << '\n';
}

C. Add One

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

思路:

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

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

init:dp[0][i]=1dp(i,j)=j<9 ? dp(i1,j+1):(dp(i1,0)+dp(i1,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 << "\n";
}

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

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

  • dpi=2, i in [0,8]

  • dpi=3, if i=9

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

  • 对于其他情况:dpi=dpi9+dpi10

    长度是 i9 次运算和 i10 次运算的和

这里同样先预处理

最后的答案为 ans=i=1|s|((m+(int)(s[i]0)<10)?1:dpm10+(int)(s[i]0))

  • 时间复杂度为: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 << "\n";
    }
    return 0;
}
posted @   RioTian  阅读(90)  评论(0编辑  收藏  举报
编辑推荐:
· 探究高空视频全景AR技术的实现原理
· 理解Rust引用及其生命周期标识(上)
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析
· 没有源码,如何修改代码逻辑?
· 一个奇形怪状的面试题:Bean中的CHM要不要加volatile?
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· Obsidian + DeepSeek:免费 AI 助力你的知识管理,让你的笔记飞起来!
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 全程不用写代码,我用AI程序员写了一个飞机大战
历史上的今天:
2020-04-12 KMP算法-从头到尾彻底理解KMP
2020-04-12 HihoCoder-Trie树
2020-04-12 理解 Hanoi 汉诺塔非递归算法
点击右上角即可分享
微信分享提示

📖目录