[trick] AGC047C Product Modulo
求 \(\sum\limits_{i=1}^n\sum\limits_{j=i+1}^n (a_i * a_j \bmod P), P = 200003\)。
取 \(P\) 的一个原根 \(g = 2\),那么 \([1,P-1]\) 可以映射到 \(g^{[0,P-2]}\) 上。
令 \(a = g^x,b = g^y\),那么有 \(a*b \bmod P = g^x * g^y \bmod P = g^{(x+y)\bmod {(P-1)}}\),直接 \(fft\) 即可。
时间复杂度 \(\mathrm{O(P\log P)}\)。
\(\texttt{Code:}\)
#include <bits/stdc++.h>
#define ll long long
#define pb push_back
#define mp make_pair
#define fi first
#define se second
using namespace std;
int read() {
int x = 0; int f = 0; char c = getchar();
while (!isdigit(c)) f |= c == '-', c = getchar();
while (isdigit(c)) x = x * 10 + (c ^ 48), c = getchar();
return f ? -x : x;
}
const int cmd = 200003;
int fpow(int a, int b) {
int res = 1;
for (; b; b >>= 1, a = 1ll * a * a % cmd)
if (b & 1) res = 1ll * res * a % cmd;
return res;
}
int add(int a, int b) {a += b; return a < cmd ? a : a - cmd;}
int sub(int a, int b) {a -= b; return a < 0 ? a + cmd : a;}
const int N = (1 << 19) + 5;
namespace Poly {
struct CP {
double x, y;
CP operator + (const CP &a) const {return (CP){x + a.x, y + a.y};}
CP operator - (const CP &a) const {return (CP){x - a.x, y - a.y};}
CP operator * (const CP &a) const {return (CP){x * a.x - y * a.y, x * a.y + y * a.x};}
};
const double pi = acos(-1);
int rev[N];
void fft(CP *f, int n, int tp) {
for (int i = 0; i < n; i++) {
rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? n >> 1 : 0);
if (i < rev[i]) swap(f[i], f[rev[i]]);
}
for (int len = 2; len <= n; len <<= 1) {
CP w0 = (CP){cos(2.0 * pi / len), sin(2.0 * pi / len) * tp};
for (int s = 0; s < n; s += len) {
CP w = (CP){1, 0};
for (int i = 0; i < (len >> 1); i++) {
CP cur = w * f[s + (len >> 1) + i];
f[s + (len >> 1) + i] = f[s + i] - cur;
f[s + i] = f[s + i] + cur;
w = w * w0;
}
}
}if (tp == -1)
for (int i = 0; i < n; i++) f[i].x = (ll)(f[i].x / n + 0.5);
}
void tms(CP *f, CP *g, int n) {
for (int i = 0; i < n; i++) f[i] = f[i] * g[i];
}
void FFT(CP *f, int m) {
int n = 1; for (; n <= m + m; n <<= 1);
fft(f, n, 1); tms(f, f, n);
fft(f, n, -1);
}
}using namespace Poly;
int n, g[N], ys[N], cnt[N];
CP f[N]; ll ans;
int main() {
#ifdef LOCAL
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
#endif
ys[g[0] = 1] = 0;
for (int i = 1; i < cmd - 1; i++) {
g[i] = (g[i - 1] << 1) % cmd;
ys[g[i]] = i;
}
n = read();
for (int i = 1; i <= n; i++) {
int a = read();
if (a) ++cnt[ys[a]], ans -= 1ll * a * a % cmd;
}
for (int i = 0; i < cmd - 1; i++) f[i] = (CP){(double)cnt[i], 0};
FFT(f, cmd - 2);
for (int i = 0; i < cmd - 1; i++)
ans += 1ll * g[i] * ((ll)f[i].x + (ll)f[i + cmd - 1].x);
printf("%lld", ans >> 1);
return 0;
}