为了能到远方,脚下的每一步都不能少.|

园龄:粉丝:关注:

2023-02-12 15:00阅读: 34评论: 0推荐: 0

Toyota Programming Contest 2023 Spring Qual A(AtCoder Beginner Contest 288)

Toyota Programming Contest 2023 Spring Qual A(AtCoder Beginner Contest 288)

D、F

被D干碎了题目连接

D - Range Add Query

题意

给定一个长度为N的序列,当且仅当它可以满足以下条件时,它是一个好序列:

  • 操作:选择两个整数i, c,满足(i+k1N),给序列的[i, i+k-1]都加上c。
  • 经过任意次操作,整个序列的值为0。

现在给定一个长度为N的序列,有q次询问,每次询问区间[l, r], 问[l, r]组成的数是否是好区间。

k <= 10, n,q <= 2e5

分析

考虑暴力,如果一个区间可以经过上述操作变成好区间,那么从前往后的模拟一定存在解,我们只需要对当前位进行+a[i], 后k-1项做-a[i], 最后k项如果全部相等那么就满足题意。时间复杂度在O(qnk)),超时。

考虑差分,纸面上的差分很难维护出我们想要的信息,我能想到的就是乱搞求出最后k个数的值,很显然不是正解。

考虑题目给的信息

  1. k是个定值
  2. 每次差分是对长度为k的区间操作,也是就a[x]+c, a[x+k]-c
  3. 差分不会改变a[x]+a[x+k]?

第三点是解题的关键,对下标为x, x+k, x+2k, x+3k ...这样的值进行差分,那么这些下标对应的值的和sum = a[x] + a[x+k]+...+a[x+tk]是不变的,因为 对于每个差分过程有a[x]+c, a[x+k]-c, sum+c-c=sum。那么现在对于一个序列a[l, r],每次进行差分会有什么结果呢,x, x+k,x+2k...的值全部差分到一处,我们假定差分到x,那么对于前k个值,最后可以是(sum1,sum2,sum3,...,sumk,0,0,0,0,...)。所以我们的问题就是求出区间(%k)值的和。可以预处理前缀和。

时间复杂度O(n+qk)

const int N = 200010;
ll n, k, q;
void solve() {
    cin >> n >> k;
    vector<int> a(n + 1, 0);
    vector<vector<int>> s(n + 1, vector<int>(k + 1, 0));
    for (int i = 1; i <= n; i++) {
        cin >> a[i];
        s[i][i % k] += a[i];
    }
    for (int i = 1; i <= n; i++) {
        for (int j = 0; j < k; j++) {
            s[i][j] += s[i - 1][j]; 
        }
    }
    cin >> q;
    for (int i = 1; i <= q; i++) {
        int l, r;
        cin >> l >> r;
        vector<int> b(k);
        for (int j = 0; j < k; j++) {
            b[j] = s[r][j] - s[l - 1][j];
        }
        if (b == vector(k, b[0])) {
            cout << "Yes\n";
        } else {
            cout << "No\n";
        }
    }
}

E - Wish List

待补

F - Integer Division

题意

给一个位数为N(N<2e5)的数,现在可以任意将数划分成m个数,每次划分后所有数的乘积为x,求出所有划分的乘积和。

比如样例 234 划分成:234234234234 结果为418。

分析

考虑动态规划,定义dp[i],为考虑了前i个字符的最大乘积和。很容易得出转移方程

dp[i]=j=0i1dp[j]X[j+1:i](X[l:r]num[l,r])

暴力的时间复杂度:枚举j加上求X[j+1,i],接近O(n3)

对转移方程进行化简,首先考虑:

X[j+1:i]=X[j+1:i1]10+X[i:i];

代入方程

dp[i]=j=0i1dp[j](X[j+1:i1]10+X[i:i]);

dp[i]=j=0i2dp[j]X[j+1:i1]10+j=0i1dp[j]X[i:i];

dp[i]=dp[i1]10+j=0i1dp[j]X[i:i]

最后求下前缀和、取模就ok了,时间复杂度为O(n)

const int mod = 998244353;
int n;
string s;
void solve() {
    cin >> n;
    cin >> s;
    s = "#" + s;
    vector<ll> dp(n + 1, 0);
    dp[1] = s[1] - '0';
    ll pre = 1 + dp[1];
    for (int i = 2; i <= n; i++) {
        dp[i] = (10 * dp[i - 1] % mod + (pre * (s[i] - '0'))) % mod;
        pre = (pre + dp[i]) % mod;
    }
    cout << dp[n] << '\n';
}

本文作者:rufu

本文链接:https://www.cnblogs.com/rufu/p/17113837.html

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   迷糊的Rufu  阅读(34)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起