小猴编程周赛C++ | 2022年秋第10周T3修改数组

学习C++从娃娃抓起!记录下在学而思小猴编程学习过程中的题目,记录每一个瞬间。侵权即删,谢谢支持!

附上汇总贴:小猴编程C++ | 汇总-CSDN博客


【题目描述】
给定一个长度为 n n n的数组 A = { a 1 , a 2 , … , a n } A=\{a_1,a_2,\dots,a_n\} A={a1,a2,,an}和一个整数 k k k。现在我们想在数组 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an中删除连续的一段 a l , a l + 1 , … , a r a_l,a_{l+1},\dots,a_r al,al+1,,ar(也可以不删除),使得数组 A A A中剩余元素的和能够被 k k k整除且数组 A A A不为空。
请你输出需要删除子数组的最短长度,即 r − l + 1 r-l+1 rl+1的最小的值,如果无法满足上述要求,输出 − 1 -1 1
【输入】
第一行,包含两个整数 n , k n,k n,k
第二行,包含 n n n个整数 a 1 , a 2 , … , a n a_1,a_2,\dots,a_n a1,a2,,an
【输出】
一行,一个整数,表示需要删除子数组的最短长度,如果无法满足题目要求,输出 − 1 -1 1
【输入样例】

4 9 
6 3 5 2

【输出样例】

2

【代码详解】
[图片]

#include <bits/stdc++.h>
using namespace std;
int n, k, a[200005], sn;
map<int, int> sum_id;
int main()
{
    cin >> n >> k;
    for (int i=1; i<=n; i++) {  // 输入n个数
        cin >> a[i];
        sn = (sn + a[i]) % k;  // 同时求前缀和模k的余数
    }
    sum_id[0] = 0;  // sum_id保存余数对应的项目,初始0个项目余数为0
    int ans = n, sr = 0;  // ans初始为n,这样最后判断仍然是n时,说明无法满足要求
    if (sn%k==0) ans = 0;  // 特判,如果开始所有数之和模k等于0,则需删除0个长度子段
    for (int r=1; r<=n; r++) {  // 枚举r
        sr = (sr+a[r])%k;  // 求出r个数前缀和模k的余数
        int t = (sr-sn+k)%k;  // s[l-1]模k的余数t
        if (sum_id.count(t)==1) {  // 只有当包含这个余数时才进行计算
            int l = sum_id[t]+1;  // 求出l
            ans = min(ans, r-l+1);  // 比较得到最小长度
        }
        sum_id[sr] = r;  // 补充前缀和模k的余数与项数对应关系
    }
    if (ans==n) cout << -1 << endl;  // 如果ans仍为n,说明无法满足要求,输出-1
    else cout << ans << endl;  // 否则输出ans
    return 0;
}

【运行结果】

4 9 
6 3 5 2
2
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值