学习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
r−l+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