给定一个序列,问有多少种方案可以将此序列分割成3个序列元素和完全相同的子序列。(子序列不能为空)。即问有多少个点对(i,j)满足a[1]+...+a[i-1]=a[i]+a[i+1]+...+a[j]=a[j+1]+a[j+2]+...+a[n]
Input
第一行一个整数n,表示序列长度。(1<=n<=5*10^5) 第二行n个整数分别表示序列的元素。(|a[i]|<=10^9)
Output
输出一个整数表示答案。
Examples
Input
5 1 2 3 0 3
Output
2
Input
4 0 1 -1 0
Output
1
Input
2 4 1
Output
0
首先求出他们的前缀和sum[i],要想分成相等的三部分,那么sum[n]%3肯定是0,否则直接输出0.
其次前缀和里要存在sum[n]/3,sum[n]/3*2才能分成三部分(可以手写试一下),我们从头开始找sum[n]/3的数量,等找到第一个sum[n]/3*2时,加上sum[n]/3的数量就是答案。
AC代码:
#include<stdio.h>
#include <iostream>
#include<string.h>
#include<map>
using namespace std;
#define ll __int64
ll a[500050];
ll sum[500050];
map<int,int>mapp;
int main()
{
int n;
while(scanf("%d",&n)!=EOF)
{
memset(sum,0,sizeof(0));
for(int i=1;i<=n;i++)
{
cin>>a[i];
sum[i]=sum[i-1]+a[i];//前缀和
}
long long summ=sum[n];
if(summ%3)
{
cout<<0<<endl;
}
else
{
long long s1=sum[n]/3;
long long s2=sum[n]/3*2;
int cnt=0;
long long ans=0;
for(int i=1;i<n;i++)
{
if(sum[i]==s2)ans+=cnt;
if(sum[i]==s1) cnt++;
}
cout<<ans<<endl;
}
}
}