1 条题解
-
0
思路与算法
令t=D-C,则B=A+2t、C>=A+8t+1。按t枚举,用频次计算AB对前缀和、CD对后缀和,一次扫描同时累计每个数值在A/B/C/D四个角色的逐件计数。
正确性说明
固定t后AB和CD两对独立,只受C>=A+8t+1的分离限制。对A/B角色乘另一个AB值频次及合法CD后缀对数;对C/D角色乘另一CD值频次及合法AB前缀对数,恰为固定这一件物品后的其余三件选择数。逐t互斥且覆盖所有魔法阵,所以累加正确。
复杂度
O(n²/9+m)时间、O(n+m)空间,含频次、四角色数组初始化与输出;实际枚举长度和约n²/18。
易错点
除以3按实数不等式解释,等价3(B-A)<C-B,不能先整除截断。给某一物品输出时,不再乘它自身值的频次;重复数值的不同编号仍有独立选择。
参考代码(C++11)
#include <bits/stdc++.h> using namespace std; int main() { ios::sync_with_stdio(false); cin.tie(nullptr); int n, m; cin >> n >> m; vector<long long> f(n + 1); vector<int> a(m); for (int &v : a) { cin >> v; f[v]++; } vector<array<long long, 4>> ans(n + 1); for (int t = 1; 9 * t + 2 <= n; t++) { long long suf = 0, pref = 0; for (int c = 8 * t + 2; c <= n - t; c++) suf += f[c] * f[c + t]; for (int a = 1; a <= n - 9 * t - 1; a++) { int b = a + 2 * t, c = a + 8 * t + 1, d = c + t; ans[a][0] += f[b] * suf; ans[b][1] += f[a] * suf; suf -= f[c] * f[d]; pref += f[a] * f[b]; ans[c][2] += f[d] * pref; ans[d][3] += f[c] * pref; } } for (int v : a) cout << ans[v][0] << ' ' << ans[v][1] << ' ' << ans[v][2] << ' ' << ans[v][3] << "\n"; }
- 1