前缀和:求部分和的利器之K倍区间/数组拆分

数组A[]={1,2,3,……}

S[i]=s[i-1]+A[i]//s[i]表示A[0]+……+A[i]

1.K倍区间
给定一个长度为N的数列,A1, A2, ... AN,如果其中一段连续的子序列Ai, Ai+1, ... Aj(i <= j)之和是K的倍数,我们就称这个区间[i, j]是K倍区间。  
你能求出数列中总共有多少个K倍区间吗?
第一行包含两个整数N和K。(1 <= N, K <= 100000)  
以下N行每行包含一个整数Ai。(1 <= Ai <= 100000)
例子:
A = [1, 2, 3, 4, 5], K = 2
答案是6:[1, 2, 3], [1, 2, 3, 4], [2], [2, 3, 4, 5], [3, 4, 5], [4]


利用前缀和:A[i]+……+A[j]=s[j]-s[i-1]
思路:
枚举起点Ai和终点Aj,计算部分和SUM = s[j] – s[i-1]
如果SUM是K倍数,ans++
for i = 1 … N:
  for j = i … N:
    sum = s[j] – s[i-1]
if sum % K == 0:
      ans++   
  
此思路运行超时

package K倍区间;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n,k;
		Scanner in=new Scanner(System.in);
		n=in.nextInt();
		k=in.nextInt();
		int a[]=new int[n+1];
		int sum[]=new int[n+1];
		for(int i=1;i<=n;i++){
			a[i]=in.nextInt();
			sum[i]=sum[i-1]+a[i];
		}
		int ants=0;
		for(int i=1;i<=n;i++){
			for(int j=i;j<=n;j++){
				if((sum[j]-sum[i-1])%k==0) ants++;
			}
		}
		System.out.println(ants);
	}

}
2.数组拆分
给定一个长度为N的数组A=[A1, A2, … AN],请你将A拆分成3段连续的子数组:
A1, A2, … Ap | Ap+1, Ap+2, … Aq | Aq+1, Aq+2, … AN

S1 = A1 + A2 + … Ap
S2 = Ap+1 + Ap+2 + … Aq
S3 = Aq+1 + Aq+2 + … AN
问有多少种划分方案可以使得S1, S2, S3两两相差不超过1.
N <= 100000,  -1000000 <= Ai <= 1000000


简单思路:枚举边界p,q的位置,利用前缀和计算s1,s2,s3

package 数组拆分;

import java.util.Scanner;

public class Main {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		int n;
		Scanner in=new Scanner(System.in);
		n=in.nextInt();
		int a[]=new int[n+1];
		int sum[]=new int[n+1];
		for(int i=1;i<=n;i++){
			a[i]=in.nextInt();
			sum[i]=sum[i-1]+a[i];
		}
		int s1,s2,s3,ants=0;
		for(int p=1;p<=n-2;p++){
			for(int q=p+1;q<=n-1;q++){
				s1=sum[p]-sum[0];
				s2=sum[q]-sum[p];
				s3=sum[n]-sum[q];
				if(Math.abs(s1-s2)<=1&&Math.abs(s2-s3)<=1&&Math.abs(s3-s2)<=1){
					ants++;
				}
			}
		}
		System.out.println(ants);
	}

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值