【Java·前缀和】AcWing 3956. 截断数组(每日一题)

蓝桥杯集训·每日一题

3956. 截断数组

https://www.acwing.com/problem/content/description/3959/
给定一个长度为 n 的数组 a1,a2,…,an。

现在,要将该数组从中间截断,得到三个非空子数组。

要求,三个子数组内各元素之和都相等。

请问,共有多少种不同的截断方法?

输入格式
第一行包含整数 n。

第二行包含 n 个整数 a1,a2,…,an。

输出格式
输出一个整数,表示截断方法数量。

数据范围
前六个测试点满足 1≤n≤10。
所有测试点满足 1≤n≤105,−10000≤ai≤10000。

输入样例1:
4
1 2 3 3
输出样例1:
1
输入样例2:
5
1 2 3 4 5
输出样例2:
0
输入样例3:
2
0 0
输出样例3:
0

代码

import java.io.*;
import java.util.*;

/**
 * @author: ZZJ
 * @date: 2023/02/13
 * @desc:
 */
public class Main {


    public static void main(String[] args) throws IOException {
        Scanner scanner = new Scanner(System.in);
        int n = scanner.nextInt();
        int[] ints = new int[n+1];
        for (int i = 1; i <= n; i++) {
            ints[i] = scanner.nextInt();
            ints[i]+=ints[i-1]; // 加上i前所有数总和,ints[i]表示i前总和
        }
        if (ints[n] % 3 != 0) {
            System.out.println(0);
            return;
        }
        long res = 0; // 注意是long类型,防止超出
        for (int i = 3,cnt = 0; i <= n; i++) {
            if (ints[i-2] == ints[n] / 3) cnt++;
            if (ints[n] - ints[i-1] == ints[n] / 3) res+=cnt; // // i-1到n的和 多少个i+多少个j
//        long res = 0;long cnt = 0; // 同理
//        for (int i = 2; i < n; i++) {
//            if (ints[i-1] == ints[n] / 3) cnt++;
//            if (ints[i] == ints[n] / 3 * 2) res+=cnt;
//        }
        }
        System.out.println(res);
    }
}

最优解

思路
本题要求将原数组截成三段,每一段的元素和都相同,设数组全部元素的和为S,那么每一段的和就是S/3,如果S模3不为零代表答案为0。设第一段的终点为L,设第二段的终点为R,第三段的终点也就是最后一点n。

0-L的元素和为S/3,0-R的元素和为2S/3,0-n的元素和为S
根据上面这句话我们就可以使用前缀和来解决这道题
首先求出数组的前缀和,指针i遍历前缀和
当i指向的前缀和数组等于S/3的时候,cnt++;
当i指向的前缀和数组等于2
S/3的时候,结果res加上cnt即可,在程序中这一步要与上一步顺序倒一下,防止S=0的情况,结果变大。
答案其实就是L与R的合法组合,R>L,并且R

作者:热的干面
链接:https://www.acwing.com/solution/content/169310/
来源:AcWing
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

import java.io.*;
import java.util.*;

public class Main{
    static BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
    static StreamTokenizer in = new StreamTokenizer(br);
    static PrintWriter out = new PrintWriter(new BufferedOutputStream(System.out));

    public static int nextInt()throws Exception{
        in.nextToken();
        return (int)in.nval;
    }
    static int N = 100010;
    static int n;
    static int[] s = new int[N];
    public static void main(String[] args)throws Exception{
        n = nextInt();
        for(int i =1;i<=n;i++){
            s[i]+=s[i-1]+nextInt();
        }
        if(s[n]%3!=0||n<3){
            out.print("0");
            out.close();
            return;
        }
        int s1 = s[n]/3;
        int s2 = s1*2;
        long cnt = 0;
        long res = 0;
        for(int i =1;i<=n;i++){
            if(s[i]==s2&&i<n) res+=cnt;
            if(s[i]==s1) cnt++;
        }
        out.print(res);
        out.close();
    }
}

总结:前缀和常考
【Java·前缀和】AcWing 3956. 截断数组(每日一题)_第1张图片

你可能感兴趣的:(每日一题,java,蓝桥杯,算法,数据结构)