zoukankan      html  css  js  c++  java
  • 【数学+思维】ZZULIOJ 1531: 小L的区间求和

    题目链接

    • 题目描述
    在给定的一个整数序列中,小L希望找到一个连续的区间,这个区间的和能够被k整除,请你帮小L算一下满足条件的最长的区间长度是多少。
    输入
    第一行输入两个整数n、k。(1 <= n <= 105,1<=k<100)
    接下来一行输入n个整数,表示序列中的数。
    输出
    输出一个整数,满足条件区间的最长长度,如果不存在,输出0
    • 样例输入
    5 7
    1 2 4 1 1
    • 样例输出
    3

    题解:
    先将数组的前缀和数组构建起来。在构建过程中模K,所以此时前缀和数组中所有数属于[0,K-1],假如有两个位置i,j,前缀和数组pre[i] == pre[j],那么不模K的前缀和数组 pre[j]-pre[i]的结果一定是K的倍数,j-i就是长度。
    所以我们的目的就成不断的了找:pre[i] == pre[j],保存长度 = j-i并更新。下面代码用:map首先都初始化为-1,之后遍历过程中遇到了就记录pre[i]的值第一次出现的位置


    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int NN = 1e5;
    
    int N,K;
    int a[NN+10];//源数组 
    int pre[NN+10];//前缀和数组 
    map<int,int> mp; //mp[n] = i 表示前缀和数组中数字n在位置i第一次出现 
    int main(){
        cin>>N>>K;
        for(int i =1;i<=N;i++){ //读入数据 
            scanf("%d",&a[i]);
        }    
        for(int i = 1;i<=N;i++){ //构建前缀和数组并取余K 
            pre[i] = (a[i]+pre[i-1])%K;
            mp[pre[i]] = -1;//都初始化为-1
        }
        int maxlen = 0; //最长长度 
        for(int i = 1;i<=N;i++){
            if(mp[pre[i]] == -1){  
                mp[pre[i]] = i;//改成第一次出现的位置 
            }else{
                maxlen = max(maxlen,i-mp[pre[i]]);//i是pre[i]此时的位置 mp[pre[i]]是pre[i]第一次出现的位置,两个相减为k的倍数 
            }
        }
        cout<<maxlen<<endl;
        return 0;
    }

     另一种用vector的写法,vector存前缀和数组元素出现的位置

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int NN = 1e5;
    
    int N,K;
    int a[NN+10];//源数组 
    int pre[NN+10];//前缀和数组 
    vector<int> ve[110];
    int main(){
        cin>>N>>K;
        for(int i =1;i<=N;i++){ //读入数据 
            scanf("%d",&a[i]);
        }    
        ve[0].push_back(0);
        for(int i = 1;i<=N;i++){ //构建前缀和数组并取余K 
            pre[i] = (a[i]+pre[i-1])%K;
            ve[pre[i]].push_back(i);
        }
        int maxlen = 0;
        for(int i = 0;i<K;i++){
            if(ve[i].size()>1)
                maxlen = max(maxlen,ve[i][ve[i].size()-1] - ve[i][0]); //最后一次出现的位置 - 第一次出现的位置 
        }
        cout<<maxlen<<endl;
        return 0;
    }


  • 相关阅读:
    无穷字符串问题--CSDN上的面试题(原创)
    c语言:将二进制数按位输出
    构造和为指定值的表达式:±1±2±3±4±5=3 确定符号
    c语言:最长对称子串(3种解决方案)
    最长公共子串
    ie7下 滚动条内容不动问题
    沙盒密探——可实现的js缓存攻击
    yii2归档安装
    php 安装composer
    [转]-Android Studio 快捷键整理分享-SadieYu
  • 原文地址:https://www.cnblogs.com/bigbrox/p/11347682.html
Copyright © 2011-2022 走看看