序列中任意个连续的元素组成的子序列称为该序列的子串。
现在给你一个序列P和一个整数K,询问元素和是K的倍数的子串的最大长度。
比如序列【1,2,3,4,5】,给定的整数K为 5,其中满足条件的子串为{5}、{2,3}、{1,2,3,4}、{1,2,3,4,5},
那么答案就为 5,因为最长的子串为{1,2,3,4,5};如果满足条件的子串不存在,就输出 0。
输入描述:
第一行包含一个整数N, 1 ≤ ? ≤ 105。
第二行包含 N 个整数??,??表示序列P第i个元素的值。0 ≤ ?? ≤ 105。第三行包含一个整数K,1 ≤ ? ≤ 105。
输出描述:
输出一个整数ANS,表示答案。
示例1
输入
5 1 2 3 4 5 5
输出
5
示例2
输入
6 3 1 2 7 7 7 4
输出
5
这一道题目穷举所有字串, 并判断的时间复杂度是O(N^3), 很容易优化到O(N^2), 但只能通过40%。 进一步优化到O(N) ,计算出所有前缀和,并模k,问题等价于判断,相隔最远的i,j,使得s[i]==s[j], 使用Hash表优化到O(N)
#include <iostream>
#include <algorithm>
#include <unordered_map>
using namespace std;
const int N = 100010;
int num[N];
int s[N];
int main()
{
int n, k, res = 0;
scanf("%d", &n);
for (int i = 0; i < n; i++) scanf("%d", &num[i]);
scanf("%d", &k);
unordered_map<int, int> mp;
s[0] = 0;
for (int i = 1; i <= n; i++) {
s[i] = (s[i - 1] + num[i-1])%k;
}
mp[0] = 0;
for (int i = 1; i <= n; i++) {
if (mp.find(s[i]) != mp.end()) {
res = max(res, i - mp[s[i]]);
}
else mp[s[i]] = i;
}
cout << res << endl;
}