0
点赞
收藏
分享

微信扫一扫

3956. 截断数组(前缀和)


文章目录

  • ​​Question​​
  • ​​Ideas​​
  • ​​Code​​

Question

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

Ideas

前缀和+枚举,重点是理解为什么可以优化成枚举一个端点

Code

#include <iostream>

using namespace std;
const int N = 1e5 + 10;
int a[N];

typedef long long LL; // 范围是1e5, 从里面选两个边界点,1e10 > int (范围2e9) 会爆int
int main()
{
int n;
scanf("%d", &n);

// 前缀和
for (int i = 1; i <= n; i ++)
{
scanf("%d", &a[i]);
a[i] += a[i - 1];
}


// 要三等分和必须是3的倍数

if (a[n] % 3) puts("0");
else
{
LL cnt = 0, total = 0; // 防止爆int
// 遍历j,满足第一部分为S/3,最后一部分为S/3即满足条件;
for (int j = 2; j < n; j ++) // 集合不能存在空集,所以j的遍历范围为[2,n-1];
{
if (a[j - 1] == a[n] / 3) cnt ++; // 第一部分满足条件
if (a[j] == a[n] / 3 * 2) total += cnt; // 第二部分满足条件
}

printf("%lld", total);
}

return 0;
}


举报

相关推荐

0 条评论