1 条题解
-
0
问题重述
给定一个质数 ,一个长度为 的数组 (元素互异,且 ),以及一个整数 ()。
$$(a_i \oplus a_j) \cdot (a_i^2 \oplus a_j^2) \equiv k \pmod p $$
定义运算 ,表面上是“按位异或”,但实际上链接中的小游戏揭示 表示乘法。
求满足下式的下标对 的数量():题意转化: 的真实含义
题目中 [bitwise XOR operation] 的链接指向一个 Wordle 游戏。解出单词为 MULTIPLY(乘法)。
因此实际运算为:代入原式:
$$(a_i \times a_j) \cdot (a_i^2 \times a_j^2) \equiv k \pmod p $$结论:问题转化为求
且 的配对数量。
算法推导
固定 ,我们需要快速统计在 之前有多少个 满足:
由于 是质数,利用费马小定理可以求逆元:
对于任意非零元 ,有 (前提 )。我们可以从左到右遍历数组,维护一个哈希表
mp,键为 ,值为其出现次数。
对于当前元素 :- 计算 。
- 如果 ,计算 ,则与 配对的 需要满足 。
- 在答案中累加
mp[k * inv % p]。 - 更新
mp[x]++。
注意几个特殊情况:
- :条件变为 。由于 是质数,无零因子,即至少一个 ,即 。
题目保证所有元素互异,因此数组中至多一个 。
如果存在 ,则它与任何其他元素配对均满足 ,故答案为 ;否则为 。 - 且 :方程变为 ,不成立。因此 不可能与任何 配对(因为 )。代码中直接
continue跳过。
标准程序详解
#include <bits/stdc++.h> using namespace std; #define ll long long int a[300005]; // 快速幂:计算 x^n mod p ll power(ll x, int n, int p) { x %= p; ll res = 1; while (n) { if (n & 1) res = (res * x) % p; x = (x * x) % p; n >>= 1; } return res; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int n, p, k; cin >> n >> p >> k; for (int i = 1; i <= n; ++i) { cin >> a[i]; } // 特判 k=0 if (k == 0) { // 只有数组中存在0时,0与其他任意元素配对成立,答案为 n-1 cout << (*min_element(a + 1, a + n + 1) == 0 ? n - 1 : 0) << '\n'; return 0; } map<int, int> mp; ll ans = 0; for (int i = 1; i <= n; ++i) { if (a[i] == 0) continue; // k != 0 时,0无法满足方程 int x = power(a[i], 3, p); // a_i^3 mod p int inv = power(x, p - 2, p); // 费马小定理求逆元 ans += mp[(k * (ll)inv) % p]; // 统计前面满足 a_j^3 ≡ k * inv 的元素数 ++mp[x]; // 将当前 a_i^3 加入哈希表 } cout << ans << '\n'; return 0; }
- 1
信息
- ID
- 6750
- 时间
- 4000ms
- 内存
- 256MiB
- 难度
- 5
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者