截断数组(蓝桥杯每日一题)

淡淡的烟草味﹌ 2024-03-26 12:32 202阅读 0赞

截断数组(蓝桥杯每日一题)

给定一个长度为 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

算法思路

这是一个前缀和的应用,如果这个数组可以分割,那么代表这个数组的总和对三取余为0。

然后如何统计分割次数了,在可以分的前提下,如果当前的数的前缀和是总和的1/3的时候,代表的是这个可以分割了,后面的那1/3就是固定的了,那么结果就可以加上了,如果当前数的前缀和是总和的1/3,那么代表这是一个新的方式,那么当前可以加的tmp就需要+1。

C++版本

  1. #include<bits/stdc++.h>
  2. using namespace std;
  3. int n;
  4. const int N = 1e5 + 10;
  5. int num[N];
  6. long long sum;
  7. int main()
  8. {
  9. cin >> n;
  10. for (int i = 1; i <= n; ++ i)
  11. {
  12. cin >> num[i];
  13. sum += num[i];
  14. }
  15. if(sum % 3 != 0) cout << "0";
  16. else
  17. {
  18. long long ave = sum / 3;
  19. long long nowSum = 0, tmp = 0;
  20. long long ans = 0;
  21. for (int i = 1; i < n; ++ i)
  22. {
  23. nowSum += num[i];
  24. if (nowSum == 2 * ave) ans += tmp;
  25. if (nowSum == ave) ++ tmp;
  26. }
  27. cout << ans << endl;
  28. }
  29. return 0;
  30. }

Java版本

  1. import java.util.*;
  2. public class Main{
  3. static int N = 100010;
  4. static int n, m;
  5. static long res;
  6. static int[] a = new int[N];
  7. static int[] s = new int[N];
  8. public static void main(String[] args){
  9. Scanner scan = new Scanner(System.in);
  10. n = scan.nextInt();
  11. for (int i = 1; i <= n; i ++) a[i] = scan.nextInt();
  12. for (int i = 1; i <= n; i ++) s[i] = s[i - 1] + a[i];
  13. if (s[n] % 3 != 0 || n < 3)
  14. {
  15. System.out.println(0);
  16. return;
  17. }
  18. int dex = s[n] / 3;
  19. for (int i = 1; i < n; i ++)
  20. {
  21. if (s[i] == dex * 2) res += m;
  22. if (s[i] == dex) ++ m;
  23. }
  24. System.out.println(res);
  25. }
  26. }

发表评论

表情:
评论列表 (有 0 条评论,202人围观)

还没有评论,来说两句吧...

相关阅读

    相关 字符串删减(每日)

    字符串删减 给定一个由 n个小写字母构成的字符串。 现在,需要删掉其中的一些字母,使得字符串中不存在连续三个或三个以上的 x。 请问,最少需要删掉多少个字母? 如果