题目描述
Farmer John’s NN cows are standing in a row, as they have a tendency to do from time to time. Each cow is labeled with a distinct integer ID number so FJ can tell them apart. FJ would like to take a photo of a contiguous group of cows but, due to a traumatic childhood incident involving the numbers 1 \ldots 61…6, he only wants to take a picture of a group of cows if their IDs add up to a multiple of 7.
Please help FJ determine the size of the largest group he can photograph.
给你n个数,分别是a[1],a[2],…,a[n]。求一个最长的区间[x,y],使得区间中的数(a[x],a[x+1],a[x+2],…,a[y-1],a[y])的和能被7整除。输出区间长度。若没有符合要求的区间,输出0。
输入输出格式
输入格式:
The first line of input contains N (1 ≤ N ≤ 50,000). The next N
lines each contain the N integer IDs of the cows (all are in the range 0 … … … 1,000,000)
第一行一个整数N 下面有N行,每行一个数
输出格式:
Please output the number of cows in the largest consecutive group whose IDs sum
to a multiple of 7. If no such group exists, output 0.
输出最长的区间大小
输入输出样例
输入样例#1:
7
3
5
1
6
2
14
10
输出样例#1:
5
说明
In this example, 5+1+6+2+14 = 28.
**这道题就比较巧水 **
最简单的思路是n2把所有情况累加一下再%7判断,不断更新ans。
显然 n = 50,000,这样我们是过不去的,只有70, 那么我们先考虑优化 :
①把第二重循环写成j = i + 1;
②在循环里判断如果i与j的差小于当前答案,就直接continue;
(这和剪枝差不多来着)这样就跑的比之前快了
然后我们会惊喜的发现,该是70分还是70分
嗯。。。
那么我们可以想一下能不能在累加和数组sum[]里面做点手脚
我们可以想一下,假设a区间里的数能被7整除
那么在其他包含这个a区间的其他区间里不管有没有a区间它%7的结果都是不变的
那么我们的sum[]记录的是1到i的累加和,如果让它们等于%7的结果,那么当sum[i] == sum[j], 时i 到 j 中间的数的累加和是可以被7整除的
同时我们用贪心的思想,如果%7的话结果只有0 ~ 6,我们记录0 ~6最先出现的下标和最后出现的下标,也就是当%7 == 1到6每一种结果的最大情况,最后再比较这7种最大情况输出就行了。
代码
#include<bits/stdc++.h>
#define ll long long
#define MAXN 5000010
using namespace std;
int a[MAXN], sum[MAXN], l[MAXN], f[MAXN];
int ans = 0;
int n;
int main()
{
scanf("%d", &n);
sum[0] = 0;
for(int i = 1; i <= n; ++i){
scanf("%d", &a[i]);
sum[i] = (sum[i - 1] + a[i]) % 7;
}
for(int i = 1; i <= n; ++i) l[sum[i]] = i;
for(int i = n; i >= 1; i--) f[sum[i]] = i;
for(int i = 0; i <= 6; ++i) ans = max(ans, l[i] - f[i]);
printf("%d\n", ans);
}