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 Rust (1.42.0) (judge verdict: Accepted)

/*
fn main() {
	let mut s = String::new();
	use std::io::Read;
	std::io::stdin().read_to_string(&mut s).unwrap();
	let mut s = s.split_whitespace();
	let n: usize = s.next().unwrap().parse().unwrap();
	let a: Vec<i64> = s.map(|a| a.parse().unwrap()).collect();

}
*/

const P: i64 = 200003;
const PR: i64 = 2;

fn main() {
	let (rootpow, expindex) = {
		let mut rootpow = vec![];
		let mut expindex = vec![0; P as usize];
		let mut r = 1;
		for i in 0..P - 1 {
			expindex[r as usize] = i as usize;
			rootpow.push(r);
			r = r * PR % P;
		}
		(rootpow, expindex)
	};

	let mut s = String::new();
	use std::io::Read;
	std::io::stdin().read_to_string(&mut s).unwrap();
	let mut s = s.split_whitespace();
	let _n: usize = s.next().unwrap().parse().unwrap();
	let a: Vec<i64> = s.map(|a| a.parse().unwrap()).collect();

	let mut cnt = vec![0; P as usize - 1];
	for &a in a.iter() {
		if a != 0 {
			cnt[expindex[a as usize]] += 1;
		}
	}
	let mut c: Vec<_> = ft::convolve(&cnt, &cnt).into_iter().map(|c| c.round() as i64).collect();
	for i in 0..cnt.len() {
		let cnt = cnt[i];
		c[2 * i] -= cnt as i64;
	}

	let mut ans = 0;
	for i in 0..c.len() {
		let r = rootpow[i % (P as usize - 1)];
		ans += r * (c[i] / 2);
	}

	println!("{}", ans);
}

mod number {
	use std::ops::*;
	pub mod primitive {
		use std::ops::*;
		pub trait Bool { fn value() -> bool; }
		pub struct False {} impl Bool for False { fn value() -> bool { false } }
		pub struct True {} impl Bool for True { fn value() -> bool { true } }
		macro_rules! impl_primitive {
			($tr:ident; $($T:ty),+) => {
				pub trait $tr: Copy + Default + PartialEq + PartialOrd + Add<Output = Self> + Sub<Output = Self> + Mul<Output = Self> + Div<Output = Self> {}
				$(impl $tr for $T {})+
			};
		}
		impl_primitive![Number; i32, f64];
		impl_primitive![Float; f64];
	}

	#[derive(Default, Clone, Copy)]
	pub struct Complex<T>(pub T, pub T);

	impl<T: primitive::Number> Mul for Complex<T> {
		type Output = Self;
		fn mul(self, rhs: Self) -> Self {
			Complex(self.0 * rhs.0 - self.1 * rhs.1, self.0 * rhs.1 + self.1 * rhs.0)
		}
	}
	impl<T: Copy> MulAssign for Complex<T> where Complex<T>: Mul<Output = Complex<T>> {
		fn mul_assign(&mut self, rhs: Self) {
			*self = *self * rhs;
		}
	}
	macro_rules! impl_binops_complex {
		($(($op:ident, $method:ident)),+) => {$(
			impl<T: Copy + $op<Output = T>> $op for Complex<T> {
				type Output = Self;
				fn $method(self, rhs: Self) -> Self::Output {
					Complex((self.0).$method(rhs.0), (self.1).$method(rhs.1))
				}
			}
		)+};
	}

	macro_rules! impl_binops_complex_elem {
		(assign $(($op:ident, $method:ident)),+) => {$(
			impl<T: Copy + $op> $op<T> for Complex<T> {
				fn $method(&mut self, rhs: T) {
					(self.0).$method(rhs); (self.1).$method(rhs);
				}
			}
		)+};
	}

	macro_rules! impl_complex_float {
		($($Ts:ty),+; $F:ty) => {$(
			impl From<Complex<$Ts>> for Complex<$F> {
				fn from(src: Complex<$Ts>) -> Complex<$F> {
					Complex(src.0 as $F, src.1 as $F)
				}
			}
			impl_complex_float![$Ts => $F];
		)+};
		($($Ts:ty),+) => {$(
			impl_complex_float![$Ts => $Ts];
		)+};
		($T:ty => $F:ty) => {
			impl Complex<$T> {
				pub fn polar(rho: $F, theta: $F) -> Complex<$F> {
					Complex(rho * theta.cos(), rho * theta.sin())
				}
			}
		};
	}

	impl_binops_complex![(Add, add), (Sub, sub)];
	impl_binops_complex_elem![assign (DivAssign, div_assign)];
	impl_complex_float![f64];
	impl_complex_float![i32; f64];
}

mod ft {
	use std;
	use super::number::primitive::*;
	use super::number::Complex;

	fn dft<Inverse: Bool>(mut a: Vec<Complex<f64>>) -> Vec<Complex<f64>>
	{
		let h = a.len().trailing_zeros();
		for i in 0..a.len() {
			let j = (0..h).map(|k| (i >> k) & 1).fold(0, |r, i| r << 1 | i);
			if i < j { a.swap(i, j); }
		}
		for b in (0..h).map(|i| 1 << i) {
			let w = if Inverse::value() {
				Complex::<f64>::polar(1., std::f64::consts::PI / (b as f64))
			} else {
				Complex::<f64>::polar(1., -std::f64::consts::PI / (b as f64))
			};
			let mut z = Complex(1., 0.);
			for j in 0..b {
				for i in (0..a.len() / (2 * b)).map(|i| i * 2 * b + j) {
					unsafe {
						let s = *a.get_unchecked(i);
						let t = *a.get_unchecked(i + b) * z;
						*a.get_unchecked_mut(i) = s + t;
						*a.get_unchecked_mut(i + b) = s - t;
					}
				}
				z *= w;
			}
		}
		if Inverse::value() {
			let n = a.len();
			for elem in a.iter_mut() {
				*elem /= n as f64;
			}
		}
		a
	}

	pub fn convolve<T>(a: &[T], b: &[T]) -> Vec<f64>
	where
		T: Number,
		Complex<T>: Into<Complex<f64>>
	{
		let deg = a.len() + b.len() - 1;
		let deg_ceil = (0..).map(|i| 1 << i).take_while(|&i| i < deg).fold(0, |_, i| i << 1);
		let a: Vec<Complex<f64>> = a.iter().map(|&a| Complex(a, T::default()).into()).chain((0..deg_ceil - a.len()).map(|_| Complex::<f64>::default())).collect();
		let b: Vec<Complex<f64>> = b.iter().map(|&b| Complex(b, T::default()).into()).chain((0..deg_ceil - b.len()).map(|_| Complex::<f64>::default())).collect();
		dft::<True>(dft::<False>(a).into_iter().zip(dft::<False>(b)).map(|(a, b)| a * b).collect()).into_iter().take(deg).map(|a| a.0).collect()
	}
}