P3131 [USACO16JAN]Subsequences Summing to Sevens S

193 阅读3分钟

P3131 [USACO16JAN]Subsequences Summing to Sevens S

提交13.65k

通过3.63k

时间限制200ms

内存限制128.00MB

提交答案加入题单

题目提供者FarmerJohn2

难度普及-

历史分数100

 提交记录  查看题解

标签

USACO2016

 查看算法标签

进入讨论版

相关讨论

 查看讨论

推荐题目

 查看推荐

 洛谷推荐关闭

 展开

题目描述

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 NN (1 \leq N \leq 50,0001≤N≤50,000). The next NN

lines each contain the NN integer IDs of the cows (all are in the range

0 \ldots 1,000,0000…1,000,000).

输出格式

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.

 

#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cmath>
#include <iostream>
#include<stack>
#include<cstdlib>
#include<map>
#pragma warning(disable:4996)
using namespace std;
typedef long long ll;
const int N = 50005;
//总结  前缀和
// 问题转化成 区间x~y的前缀和mod7 == 0 求区间长度的最大值
// 
// 即(a[x] - a[y-1])%7 == 0 求 x-y+1的最大值
//若两个数相减 (mod7=0) ,那么这两个数的余数一定相同!!
//这样问题就简单了,只要求出相同余数出现的第一次和最后一次位置之间长度即是最长长度
//但我们不知道是哪个余数最长
//所以枚举0~6共7个余数各种的最长长度,然后暴力找

int a[N];
int first[9];
int last[9];
int main()
{
	int n = 0;
	cin >> n;
	int i = 0;
	for (i = 1; i <= n; i++)
	{
		cin >> a[i];
		a[i] = (a[i] + a[i-1])%7;//前缀和全都mod7
	}
	for (i = n; i >= 1; i--)//i逐渐变小,如果有出现相同的余数,会被较小值覆盖
	{
		first[a[i]] = i;
	}
	//倒着扫一遍,最后就是这个余数第一次出现的位置
	first[0] = 0;//从头加到i是7的倍数的情况下,需要把0的第一次出现设为0,即把整个区间[1,i]选上了。
	for (i = 1; i <= n; i++)
	{
		last[a[i]] = i;//最后一次出现的位置为i
	}
	//(最后一次出现减第一次出现 显然是最长的)
//两个位置相减就是长度;因为是前缀和(前缀和为【i+1,j】的区间,所以j-i即为区间的长度) 
//这里不是一般的 j-i+1(末位置 减 首位置+1) 为长度,紧扣前缀和的定义!! 
	
	int ans = 0;
	for (i = 0; i <= 6; i++)
	{
		ans = max(last[i] - first[i], ans);
	}
	cout << ans;
	
}