列表

详情


NC231441. TSUM - Triple Sums

描述

给定一个由 N不同整数组成的序列 s
考虑序列中不同索引的三个整数的所有可能的和。
对于每个可能的和,输出生成它的不同索引三元组的数量。

输入描述

第一行包含一个正整数
接下来N行,每行包含一个整数,保证没有两个整数相同。

输出描述

按以下格式打印每个可能和的解:
sum_value : number_of_triples

应首先打印较小的总和值。
具体见样例输出。

示例1

输入:

5
-1
2
3
0
5

输出:

1 : 1
2 : 1
4 : 2
5 : 1
6 : 1
7 : 2
8 : 1
10 : 1

说明:

4 可以使用三元组 ( 0, 1, 2 ) 和 ( 0, 3, 4 ) 获得。
7 可以使用三元组 ( 0, 2, 4 ) 和 ( 1, 3, 4 ) 获得。

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 71ms, 内存消耗: 13340K, 提交时间: 2021-12-10 17:46:08

#include<bits/stdc++.h>
using namespace std;
using ll = long long;
using PII = pair<int, int>;
const int N = 2e5 + 5;
const double pi = acos(-1);
int n, m, up = 1, l, r[N];
struct point {
	double x, y;
	point(double _x = 0, double _y = 0):x(_x), y(_y){}
	point operator +(point A) {return (point){x + A.x, y + A.y};}
	point operator -(point A) {return (point){x - A.x, y - A.y};}
	point operator *(point A) {return (point){x * A.x - y * A.y, x * A.y + y * A.x};}
}a[N], b[N], c[N];
void fft(point *f, int sz, int type) {
	for(int i = 1; i < sz; i++)
		if(i < r[i]) swap(f[i], f[r[i]]);
	for(int len = 1; len < sz; len <<= 1) {
		point wn(cos(pi / len), type * sin(pi / len));
		for(int j = 0; j < sz; j += len << 1) {
			point w(1, 0);
			for(int i = j; i < j + len; i++, w = w * wn) {
				point x = f[i], y = w * f[i + len];
				f[i] = x + y; f[i + len] = x - y;
			}
		}
	}
}
int A[N], B[N], C[N];
int main() {
	cin >> n;
	for(int i = 0; i < n; i++) {
		int x; cin >> x; x += 20000;
		A[x]++, B[2 * x]++, C[3 * x]++; m = max(m, x);
	}
	while(up <= 3 * m) up <<= 1, l++;
	for(int i = 0; i < up; i++)
		a[i].x = A[i], b[i].x = B[i];
	for(int i = 1; i < up; i++)
		r[i] = (r[i >> 1] >> 1) | ((i & 1) << (l - 1));
	fft(a, up, 1), fft(b, up, 1);
	for(int i = 0; i < up; i++)
		c[i] = a[i] * (a[i] * a[i] - b[i] * 3);
	fft(c, up, -1);
	for(int i = 0; i < up; i++) {
		long long x = ((ll)(c[i].x / up + 0.5) + 2 * C[i]) / 6;
		if(x) printf("%d : %lld\n", i - 60000, x);
	}
	return 0;
}

上一题