专栏文章
板子大赛之即使阿克但被【数据删除】击落导致 rk 204
AT_abc392_g题解参与者 2已保存评论 2
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 2 条
- 当前快照
- 1 份
- 快照标识符
- @miqaqv6t
- 此快照首次捕获于
- 2025/12/04 01:44 3 个月前
- 此快照最后确认于
- 2025/12/04 01:44 3 个月前
你是一名信息学竞赛选手,你精通网络,这一天,你打开 AtCoder,却发现加载一个页面需要一分钟,于是你开始打 ABC。
给定 个不同的正整数 。一个三元组 是好的,当且仅当 且 。你可以任意选出三个数组成三元组,问有多少种方法能组成一个好的三元组。两种方法不同仅当你选择的数下标至少一个不同。。
你开始瞪眼法。你注意力惊人,发现 等价于 。于是你决定枚举 统计合法的 个数:
于是你把这个放进有关值域 的桶中, 表示等于 的数个数:
你发现,后面这个求和像极了一个卷积。于是你使用了多项式,得到了数组 :
你发现对于一个合法的 , 和 在卷积中都被统计,同时 也被统计,所以你去掉了重复和非法的方案。那么答案就是:
你愉快地敲完了 FFT。交了一发。你的网速将你罚时一分钟,并在这一分钟之后成功提交了你的代码。通过了。你成功 AK 了 ABC392。
你愉快地打开榜单,却发现你打不开榜单,榜单保持在 Loading 状态。
赛后,你发现你在 AtCoder 打 ABC 时糟糕的网络状况。你关闭了它,然后成功打开榜单,却发现你是 rk 204,并且每题的罚时都比往常多五分钟,包含了开题的加载时间,提交的加载时间。
祝大家在打比赛的时候都有一个优良的网络环境。
CPP#include <bits/stdc++.h>
#define LL long long
using namespace std;
namespace COMPLEX {
struct Complex {
long double real, imag;
Complex() { real = 0; imag = 0; return ; }
Complex(long double a, long double b) { real = a, imag = b; return ; }
const void operator = (const Complex& b) {
real = b.real, imag = b.imag; return ;
}
};
const Complex operator + (const Complex& a, const Complex& b) {
return Complex(a.real + b.real, a.imag + b.imag);
}
const Complex operator - (const Complex& a, const Complex& b) {
return Complex(a.real - b.real, a.imag - b.imag);
}
const Complex operator * (const Complex& a, const Complex& b) {
return Complex(a.real * b.real - a.imag * b.imag,
a.real * b.imag + a.imag * b.real);
}
const void operator += (Complex& a, const Complex& b) {
a.real = a.real + b.real; a.imag = a.imag + b.imag; return ;
}
const void operator -= (Complex& a, const Complex& b) {
a.real = a.real - b.real; a.imag = a.imag - b.imag; return ;
}
const void operator *= (Complex& a, const Complex& b) {
a = Complex(a.real * b.real - a.imag * b.imag,
a.real * b.imag + a.imag * b.real); return ;
}
} using namespace COMPLEX;
using comp = Complex;
const int N = 5e6 + 10;
int n, m; comp F[N], G[N];
namespace FFT {
const long double PI = acosl(-1);
void arrange(comp* F, int n) {
for (int i = 0; i < n; i ++) {
int x = 0;
for (int j = 0; (1 << j) < n; j ++)
x = (x << 1) | ((i >> j) & 1);
if (i > x) continue;
swap(F[i], F[x]);
} return ;
}
void DFT(comp* F, int n, int inv) {
arrange(F, n);
for (int h = 2; h <= n; h <<= 1) {
comp omega(cosl(2 * PI / h), sinl(inv * 2 * PI / h));
for (int j = 0; j < n; j += h) {
comp cur(1, 0);
for (int k = j; k < j + h / 2; k ++) {
comp a = F[k], b = F[k + h / 2] * cur;
F[k] = a + b, F[k + h / 2] = a - b; cur *= omega;
}
}
}
if (inv == -1) {
for (int i = 0; i < n; i ++)
F[i].real /= n, F[i].imag /= n;
} return ;
}
} using FFT :: DFT;
using namespace FFT;
int trans(int x) {
int t = 1;
while (x) t <<= 1, x >>= 1;
return t;
}
int A[N], cnt[N];
int main() {
ios :: sync_with_stdio(0); cin.tie(0); cout.tie(0);
cin >> n; int m = 2e6 + 2;
for (int i = 1; i <= n; i ++) { cin >> A[i]; cnt[A[i]] ++; }
for (int i = 1; i <= m; i ++) F[i].real = F[i].imag = cnt[i];
int len = 1; while (len < m) len <<= 1;
DFT(F, len, 1);
for (int i = 0; i < len; i ++) F[i] = F[i] * F[i];
DFT(F, len, -1); LL Ans = 0;
for (int i = 1; i <= n; i ++) Ans += (LL)(F[A[i] * 2].imag / 2 + 0.5) - 1;
cout << Ans / 2 << "\n";
return 0;
}
相关推荐
评论
共 2 条评论,欢迎与作者交流。
正在加载评论...