- 题161.洛谷P3131 前缀和与差分-Subsequences Summing to Sevens S
- 一、题目
- 二、题解
题161.洛谷P3131 前缀和与差分-Subsequences Summing to Sevens S
一、题目 二、题解
看到这题,开局便想着我应该构建个前缀和数组,然后去用两个循环去求出满足被7整除的区间前缀和,但是这又毫无意外的超时了。以下是那个超时代码:
#includeusing namespace std; int N; int a[50010]; int sum[50010]; int main() { cin>>N; for(int i=1;i<=N;i++) { scanf("%d",&a[i]); sum[i]=sum[i-1]+a[i]; } int maxlen=0; for(int l=0;l 于是我们想着如何将循环再去掉一层这样去优化它。有个定理是这样的,(a-b)%c=0=>a%c=b%c,正好这里我们用前缀和数组去求区间和的方式便是sum[r]-sum[l],所以要使得(sum[r]-sum[l])%7=0对应的区间长度最大,即得到sum[l]%7=sum[r]%7,r-l值最大就好。所以关键是记录下相同余数开始出现的位置与最后出现的位置,找到他们最大差值出来就好。AC代码如下:
#includeusing namespace std; int N; int a[50010]; int sum[50010]; int pre[7],post[7]; int main() { cin>>N; for(int i=1;i<=N;i++) { scanf("%d",&a[i]); sum[i]=(sum[i-1]+a[i])%7;//因为只要知道余数的情况,所以直接存前缀和与7的余数就好 } for(int i=N;i>=0;i--)//倒着扫,找正序第一次出现的各个余数的位置 { pre[sum[i]]=i; } for(int i=0;i<=N;i++)//正着扫,找正序最后一次出现的各个余数的位置 { post[sum[i]]=i; } //切记上面两个循环都得扫到i=0,因为可能出现sum只有一个能被7整除的情况,这时候它的长度显然i-0,而不是不扫到i=0出现的i-i=0 int maxlen=0; for(int i=0;i<7;i++) { maxlen=max(maxlen,post[i]-pre[i]); } cout<



