不愧为acwing的中等题,细节是真的多,又又又阴沟翻船了。
题目要我们分成三个数组,求解又集几种分法。普遍思路是首先求解数组总和,除以3求的平均值。
第一个注意点:如果数组给的数的数量不足三个,那么返回0,如果总和除不尽3也返回0
接着我们查找几种分法,原理很简单,只要确定前两段得到分法并相乘就可以得出总分法。
因为不管前两段怎么分,剩下来的都是最后一段。那么关键问题是前两种的分法怎么求,在这里提供一种思路。我们求出前缀和后,找到一段距离,这段距离上的数字的和等于总和的三分之一,这就是第一段的最小分法子,为什么是最小分发?因为后面如果跟着0或者正负8,那么它的长度就会变长,而值不变。问题来了,如何确定第一段的最长的长度,并类推到第二段呢?我们不妨直接设个中间量aaaa,首先在前n-1个数字中寻找累加起来等于average的,找到一个aaaa++,一旦前缀和等于average*2,就证明已经到了第二段的最小长度,这时候就将answer+aaaa,为什么是加aaaa呢,原理就是总数等于第一段的数量乘以第二段的种类数,这是是把乘法变加法。
注意点:
之所以我令编号小于a,不仅仅是因为aa【a】等于average*3,还有一种特殊的样例,三个0,为了规避它的影响的,我设置这个条件,顺便
if(aa[b]==average*2) {
answer=answer+aaaa;
}
if(aa[b]==average) {
aaaa++;
}
这一块代码也是规避0 0 0的影响的设置的
好啦,这题目就是这样
总代码:
import java.awt.geom.AffineTransform;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.Scanner;
import java.util.function.IntBinaryOperator;
import java.util.function.LongBinaryOperator;
import javax.management.relation.InvalidRelationTypeException;
public class Main {
public static void main(String[] args) throws IOException {
Scanner sc=new Scanner(System.in);
BufferedReader br1=new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw1=new PrintWriter(System.out);
String[] aStrings=br1.readLine().split(" ");
int a=Integer.parseInt(aStrings[0]);
aa=new long[a+1];
String[] bStrings=br1.readLine().split(" ");
int b;
long sum=0;
for(b=1;b<=a;b++) {
aa[b]=Long.parseLong(bStrings[b-1]);
aa[b]=aa[b]+aa[b-1];
}
long average=aa[a]/3;
if(aa[a]%3!=0||a<3) {
System.out.println(0);
return;
}
long answer=0;
long aaaa=0;
for(b=1;b<a;b++) {
if(aa[b]==average*2) {
answer=answer+aaaa;
}
if(aa[b]==average) {
aaaa++;
}
}
System.out.println(answer);
}
public static long[] aa;
}