codeforces 466c

题目链接

题意

给定一个序列,问有多少种方案可以将此序列分割成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[i1]=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 sum1/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;
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值