整除k的最大连续子区间(前缀和取模)(2017美团笔试)

题意:一个数n,给出n个数,再给一个数k。求能整除k的连续区间和所在区间的最大长度。bc85场1001的升级版。

题解:刚拿到题的时候没看清是连续区间,就瞎想dp。发现连续区间后,想尺取法,发现这道题是离散的,没法尺取,也没法二分。

正解应该是前缀和取模。若(sum[j]-sum[i])%k==0则区间[i,j]的和是能整除k的。注意,前缀和的第一项是0。

预处理完成后,考虑如何求最大区间长。从前往后扫一次,记录每个值最早出现的位置。从后往前扫一次,以便记录每个值最后出现的位置。当值为0时,则记录出现的最后位置,从第一个数到该位置的区间和一定能整除k。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
int n,k,cnt;
int a[500100],sum[500100],ans[500100];
int temp[500010];
int b[500100],c[500100],d[500100];
int main(){
   while(scanf("%d",&n)!=EOF){
      memset(sum,0,sizeof(sum));
      memset(ans,0,sizeof(ans));
      for(int i=1;i<=n;i++){
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i]; //前缀和
      }
      scanf("%d",&k);
      cnt=0;
      memset(temp,0,sizeof(temp));
      for(int i=1;i<=n;i++){
        ans[i]=sum[i]%k;     //前缀和取模
        if(temp[ans[i]]==0){
            temp[ans[i]]++;
            b[ans[i]]=i;
            d[cnt++]=ans[i]; //保存值的种类
        }
        //printf("%d ",ans[i]);
      }//printf("\n");
      int res;
      memset(temp,0,sizeof(temp));
      for(int i=n;i>=1;i--){
        if(temp[ans[i]]==0){
            if(ans[i]==0){
                res=i;   //最远距离初始化为最后一个0的位置
            }
            temp[ans[i]]++;
            c[ans[i]]=i;
        }
      }
      for(int i=0;i<cnt;i++){
        //printf("tt: %d %d %d\n",d[i],b[d[i]],c[d[i]]);
        if(d[i]!=0){
            res=max(res,c[d[i]]-b[d[i]]);
        }
      }
      printf("%d\n",res);
   }
   return 0;
}

时间: 2024-10-12 16:45:42

整除k的最大连续子区间(前缀和取模)(2017美团笔试)的相关文章

51NOD 1116 K进制下的大数(字符串取模 + 枚举)

传送门 1116 K进制下的大数 基准时间限制:1 秒 空间限制:131072 KB 分值: 20 难度:3级算法题 收藏 关注 有一个字符串S,记录了一个大数,但不知这个大数是多少进制的,只知道这个数在K进制下是K - 1的倍数.现在由你来求出这个最小的进制K. 例如:给出的数是A1A,有A则最少也是11进制,然后发现A1A在22进制下等于4872,4872 mod 21 = 0,并且22是最小的,因此输出k = 22(大数的表示中A对应10,Z对应35). Input 输入大数对应的字符串S

【GDKOI2016Day1T1-魔卡少女】【拆位】线段树维护区间内所有连续子区间的异或和

题意:给出N个数,M个操作.操作有修改和询问两种,每次修改将一个数改成另一个数,每次询问一个区间的所有连续子区间的异或和.n,m<=100000,ai<=1000 题解: 当年(其实也就是今年)做不出来的题..D1T1啊... 因为ai<=1000,我们可以拆位处理.拆成10个二进制位,每位开1棵线段树. 对于每个节点,维护: d:这段区间的异或和 L[0],L[1]:子区间一定从左端点开始,异或和为0,1的子区间分别有多少个 R[0],R[1]:子区间一定从右端点开始,异或和为0,1的

hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙

/** 题目:hdu4106 区间k覆盖问题(连续m个数,最多选k个数) 最小费用最大流 建图巧妙 链接:http://acm.hdu.edu.cn/showproblem.php?pid=4106 题意:给你n个数,每连续m个数,最多选k个数,问可以选的数的权值和最大多少. 思路:可以转化为区间k覆盖问题.区间k覆盖问题是每个点最多被k个区间覆盖.本题是每个区间最多选k个点. 刚好相反.我的做法有点不同其他博客那种做法.当然本质一样. 我这里的i就是原来n个数的下标,现在作为图中该数的节点编号

连续取模

哈理工团体赛:problem E . Mod Kim刚刚学会C语言中的取模运算(mod).他想要研究一下一个数字A模上一系列数后的结果是多少.帮他写个程序验证一下. Input 第一行一个整数T代表数据组数. 接下来T组数据,第一行一个整数n,接下来n个数字ai 接下来一行一个整数m,接下来m个数字bi Output 对于每个bi,输出bi%a1%a2%...%an Sample Input Output 1 4 10 9 5 7 5 14 8 27 11 25 4 3 2 1 0 Hint 在

k进制正整数的对k-1取余与按位取余

华电北风吹 天津大学认知计算与应用重点实验室 日期:2015/8/24 先说一下结论 有k进制数abcd,有abcd%(k?1)=(a+b+c+d)%(k?1) 这是由于kn=((k?1)+1)n=∑ni=0Cin(k?1)i 因此kn 对(k-1)取余的话为1 比如10进制1425%9=3,(1+4+2+5)=12%9=3. 这个性质眼下我在两个地方见到了 (一)算法导论第11章讲散列表的时候,除法散列的时候 h(k)=kmod m 对于m的选取,若m取2p或者2p?1 均是不合适的选择,前者

POJ 3233-Matrix Power Series( S = A + A^2 + A^3 + … + A^k 矩阵快速幂取模)

Matrix Power Series Time Limit: 3000MS   Memory Limit: 131072K Total Submissions: 20309   Accepted: 8524 Description Given a n × n matrix A and a positive integer k, find the sum S = A + A2 + A3 + - + Ak. Input The input contains exactly one test cas

【美团笔试题】连续最大子序列整除k

[思路] 滑动窗口"掐头去尾" [正确代码] 1 import java.util.Scanner; 2 3 public class Main { 4 public static void main(String[] args) { 5 Scanner sc = new Scanner(System.in); 6 while (sc.hasNext()) { 7 int n = sc.nextInt(); 8 int[] arr = new int[n]; 9 for (int i

剑指offer(二十三,二十四,二十五)最小的k个数,连续子数组的最大和,链表中环的入口节点

23:最小的k个数 题目描述 输入n个整数,找出其中最小的K个数.例如输入4,5,1,6,2,7,3,8这8个数字,则最小的4个数字是1,2,3,4,. 简单题.... function GetLeastNumbers_Solution(input, k) { if(k>input.length) return []; let ans = []; input = input.sort(); //console.log(input.join("").slice(0,4).split

Codevs-4919 线段树练习4(区间加上一个值并求摸个区间整除k的数的个数,线段树+数组维护)

给你N个数,有两种操作 1:给区间[a,b]内的所有数都增加X 2:询问区间[a,b]能被7整除的个数 输入描述 Input Description 第一行一个正整数n,接下来n行n个整数,再接下来一个正整数Q,表示操作的个数. 接下来Q行每行若干个整数.如果第一个数是add,后接3个正整数a,b,X,表示在区间[a,b]内每个数增加X,如果是count,表示统计区间[a,b]能被7整除的个数 输出描述 Output Description 对于每个询问输出一行一个答案 样例输入 Sample