第八届“图灵杯”NEUQ-ACM程序设计竞赛个人赛 | 小宝的幸运数组

题目

牛客网链接
在这里插入图片描述

思路

其实我也不会,单纯解读一下别人的代码
题目要求幸运子数组中所有数的和能被k整除
小学二年级数学知识我们知道:

若 数 列 中 第 i 项 ∑ x = 1 i a x % k = c ( c 为 常 数 ) , ∑ x = 1 j a x % k = c , i < j , 则 有 ∑ x = i + 1 j a x = k × 某 一 常 数 若数列中第i项\sum _{x=1}^{i}{a_{x}}\%k=c(c为常数),\sum _{x=1}^{j}{a_{x}} \%k=c,i<j,则有\sum _{x=i+1}^{j}{a_{x}} = k \times 某一常数 ix=1iax%k=c(c)x=1jax%k=ci<jx=i+1jax=k×

所以我们只需要计算数组和的前缀和,然后把前缀和求余k,再看看何时出现了一样的余数或者被k整除即可

为了判断何时出现了一样的余数,我们声明一个数组pos来记录这个余数第一次出现的位置,-1表示未出现过,并且让pos[0]=0(被k整除的情况)
这样每次把数组和求余k以后判断pos是否为-1,如果是-1就记录余数第一次出现的位置,如果不是-1,则直接拿当前数的位置减去pos的位置,看看长度是否为最大即可

代码

#include <iostream>
#include <memory.h>

using namespace std;

int main() {
    //工具人变量temp
    int temp;
    //数据的组数T
    int T;
    //幸运数字k
    int k;
    //数组长度n
    int n;
    //数组中前i个数的和除以k的余数
    int sum[100005] = {0};
    //以sum[i]%k为下标,记录这个余数出现的第一个位置,-1表示未出现过
    int pos[100005] = {-1};

    cin >> T;
    while (T-- > 0) {
        //清一下pos数组
        memset(pos, -1, sizeof(pos));
        //如果余数为0说明第1到第i个数字的和正好被k整除
        //即幸运子数组的长度为i
        pos[0] = 0;
        //最长幸运子数组的长度
        int maxLength = -1;
        cin >> n >> k;
        for (int i = 1; i <= n; ++i) {
            cin >> temp;
            sum[i] = sum[i - 1] + temp;
            sum[i] %= k;
            //看看这个余数之前有没有出现过
            //如果没出现过,记录出现的位置
            //如果出现过,记录一下数组长度
            if (pos[sum[i]] == -1) {
                pos[sum[i]] = i;
            } else {
                maxLength = max(maxLength, (int) (i - pos[sum[i]]));
            }
        }
        cout << maxLength << endl;
    }
}
  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值