Problem:
Score : 800 points

Problem Statement

Let’s take a prime P = 200\,003.
You are given N integers A_1, A_2, \ldots, A_N.
Find the sum of ((A_i \cdot A_j) \bmod P) over all N \cdot (N-1) / 2 unordered pairs of elements (i < j).

Please note that the sum isn't computed modulo P.

Constraints

2 \leq N \leq 200\,000

0 \leq A_i < P = 200\,003

All values in input are integers.

Input

Input is given from Standard Input in the following format.

N
A_1 A_2 \cdots A_N

Output

Print one integer — the sum over ((A_i \cdot A_j) \bmod P).

Sample Input 1

4
2019 0 2020 200002

Sample Output 1

474287

The non-zero products are:

2019 \cdot 2020 \bmod P = 78320

2019 \cdot 200002 \bmod P = 197984

2020 \cdot 200002 \bmod P = 197983

So the answer is 0 + 78320 + 197984 + 0 + 0 + 197983 = 474287.

Sample Input 2

5
1 1 2 2 100000

Sample Output 2

600013

Solution in C++ (GCC 9.2.1) (judge verdict: Accepted)

#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define REP(i,n) for (ll i = 0; i < (n); ++i)

struct mint{
    static const long long MOD = 200003;

    long long v;

    mint() : v(0) {}
    mint(long long x){
        x = x % MOD;
        if(x < 0){ x += MOD; }
        v = x;
    }
    mint& operator+=(mint a){
        v += a.v;
        if(v >= MOD){ v -= MOD; }
        return *this;
    }
    mint& operator*=(mint a){
        v *= a.v;
        v %= MOD;
        return *this;
    }
    mint& operator-=(mint a){
        v -= a.v;
        if(v < 0){ v += MOD; }
        return *this;
    }
    mint& operator/=(mint a){
        return (*this) *= a.inv();
    }

    mint operator*(mint a) const{
        return mint(v) *= a;
    }

    mint operator+(mint a) const {
        return mint(v) += a;
    }

    mint operator-(mint a) const {
        return mint(v) -= a;
    }

    mint operator/(mint a) const {
        return mint(v) /= a;
    }

    mint pow(long long k) const {
        mint res(1),tmp(v);
        while(k){
            if(k&1) res *= tmp;
            tmp *= tmp;
            k >>= 1;
        }
        return res;
    }
    mint inv(){return pow(MOD - 2); }

    static mint comb(long long n, int k){
        mint res(1);
        for(int i = 0; i < k; ++i){
            res *= mint(n - i);
            res /= mint(i + 1);
        }
        return res;
    }

    static mint factorial(long long n){
        mint res(1);
        for(int i = n; i > 1; --i){
            res *= mint(i);
        }
        return res;
    }

    bool operator<(const mint &a) const {
        return v < a.v;
    };
};

mint operator*(long long l, mint r){ return r * l; }

std::ostream& operator<<(std::ostream& stream, const mint& m){
    stream << m.v;
    return stream;
}


using Complex = complex<double>;

ll pow_2_at_least(ll n){
    ll ret = 1;
    while(ret < n){ ret *= 2; }
    return ret;
}

void dft(const vector<Complex>& f, const vector<Complex>& cs,
         vector<Complex>& out, bool is_inv=false, ll h=1){
    const ll n = f.size();
    if(n == 1){
        out.resize(1);
        out.at(0) = f.at(0);
        return;
    }
    vector<Complex> f0(n / 2, 0), f1(n / 2, 0);
    REP(i, n / 2){
        f0.at(i) = f.at(2 * i);
        f1.at(i) = f.at(2 * i + 1);
    }
    vector<Complex> f02, f12;
    dft(f0, cs, f02, is_inv, 2 * h);
    dft(f1, cs, f12, is_inv, 2 * h);

    out.resize(n);
    REP(i, n){
        if(!is_inv){
            out.at(i) = f02.at(i % (n / 2)) + cs.at(h * i) * f12.at(i % (n / 2));
        }else{
            out.at(i) = f02.at(i % (n / 2)) + conj(cs.at(h * i)) * f12.at(i % (n / 2));
        }
    }
}

void idft(const vector<Complex>& f,
          const vector<Complex>& cs,
          vector<Complex>& out){
    const ll n = f.size();
    dft(f, cs, out, true);
    REP(i, n){ out.at(i) /= n; }
}

void multiply(
        vector<Complex>& g,
        vector<Complex>& h,
        vector<Complex>& out){
    const ll n = pow_2_at_least((ll)(g.size() + h.size()) - 1LL);
    vector<Complex> cs(n);
    REP(i, n){
        cs.at(i) = Complex(cos(2 * M_PI * i / n), sin(2 * M_PI * i / n));
    }
    g.resize(n, 0);
    h.resize(n, 0);

    vector<Complex> g2, h2, f2;
    dft(g, cs, g2);
    dft(h, cs, h2);
    f2.resize(n);
    REP(i, n){ f2.at(i) = g2.at(i) * h2.at(i); }
    idft(f2, cs, out);
}

vector<Complex> li2cp(const vector<ll>& f){
    vector<Complex> ret;
    transform(
        f.begin(), f.end(), back_inserter(ret),
        [](auto x) { return Complex(x); });
    return ret;
}

vector<ll> cp2li(const vector<Complex>& f){
    vector<ll> ret;
    transform(
        f.begin(), f.end(), back_inserter(ret),
        [](auto x) { return llround(x.real()); });
    return ret;
}

int main() {
    vector<ll> log(mint::MOD);
    mint g = 2;
    REP(i, mint::MOD - 1){
        log[g.pow(i).v] = i;
    }

    vector<ll> cnt(mint::MOD - 1, 0);

    ll n;
    cin >> n;
    REP(i, n){
        ll a;
        cin >> a;
        if(a != 0){ ++cnt[log[a]]; }
    }

    auto ccnt = li2cp(cnt);

    vector<Complex> cres;

    multiply(ccnt, ccnt, cres);

    auto res = cp2li(cres);

    ll ans = 0;
    REP(i, res.size()){
        ans += g.pow(i).v * res[i];
    }

    REP(i, cnt.size()){
        ans -= g.pow(i * 2).v * cnt[i];
    }

    ans /= 2;

    cout << ans << endl;
    return 0;
}