题161.洛谷P3131 前缀和与差分-Subsequences Summing to Sevens S


题161.洛谷P3131 前缀和与差分-Subsequences Summing to Sevens S


一、题目

在这里插入图片描述

二、题解

看到这题,开局便想着我应该构建个前缀和数组,然后去用两个循环去求出满足被7整除的区间前缀和,但是这又毫无意外的超时了。以下是那个超时代码:

#include <bits/stdc++.h>

using 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<N;l++)
    {
        for(int r=l;r<=N;r++)
        {
            int val=sum[r]-sum[l];
            if(val%7==0)
            {
                maxlen=max(maxlen,r-l);
            }
        }
    }
    cout<<maxlen<<endl;
}

于是我们想着如何将循环再去掉一层这样去优化它。有个定理是这样的,(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代码如下:

#include <bits/stdc++.h>

using 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<<maxlen<<endl;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值