题目链接
题意
给定一个序列,问有多少种方案可以将此序列分割成3个序列元素和完全相同的子序列。(子序列不能为空)。即问有多少个点对(i,j)满足 a [ 1 ] + . . . + a [ i − 1 ] = a [ i ] + a [ i + 1 ] + . . . + a [ j ] = a [ j + 1 ] + a [ j + 2 ] + . . . + a [ n ] a[1]+...+a[i-1]=a[i]+a[i+1]+...+a[j]=a[j+1]+a[j+2]+...+a[n] a[1]+...+a[i−1]=a[i]+a[i+1]+...+a[j]=a[j+1]+a[j+2]+...+a[n]
题解
暴力一点就好了
已知如果能分成三段相等的数据,那么把整个数组相加的和(sum值)一定可以被3整除,不能整除就是0个。
能整除的话,枚举一下J就好了
每当遇到第J个元素之前的所有数字之和为
s
u
m
sum
sum的
2
/
3
2/3
2/3倍时,答案就是加上第J个数字前的为
s
u
m
∗
1
/
3
sum*1/3
sum∗1/3的个数。第
J
J
J个元素之前的数字之和为
s
u
m
sum
sum的
2
/
3
2/3
2/3时,J后面的一段一定是
s
u
m
/
3
sum/3
sum/3,我们加上前面的就好了。
注意一下,
a
n
s
ans
ans必须为
l
o
n
g
l
o
n
g
long long
longlong
首先你一个1然后
2
e
5
2e5
2e5个0再一个1然后
3
e
5
3e5
3e5个0再一个1,答案就是
6
e
10
6e10
6e10左右(估计值)
#include<algorithm>
#include<iostream>
#include<cmath>
#include<vector>
#include<cstring>
#include<cstdio>
#define ll long long
using namespace std;
ll a[500005];
int main(void) {
int n;
while (cin >> n) {
int b;
memset(a, 0, sizeof(a));
for (int i = 1; i <= n; i++) {
cin >> b;
a[i] = a[i - 1] + b;
}
ll ans = 0, ans1 = 0;
if (a[n] % 3 != 0 || n < 3) {
cout << 0 << endl;
continue;
}
if (a[n] % 3 == 0) {
for (int i = 1; i < n; i++) {
if (a[i] == a[n] / 3 * 2)ans += ans1;//记录答案
if (a[i] == a[n] / 3)ans1++;//记录第i个以前的数字之和为sum/3的数量
}
}
cout << ans << endl;
}
return 0;
}