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)

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

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 (pows, indices) = {
		let mut r = vec![1];
		let mut ind = vec![0; P as usize];
		let mut l = 1;
		let mut i = 0;
		loop {
			l = l * PR % P;
			if l == 1 {
				break;
			}
			i += 1;
			r.push(l);
			ind[l as usize] = i;
		}
		(r, ind)
	};
	let mut poly = vec![0i64; P as usize];
	for a in s.take(n).map(|a| a.parse::<usize>().unwrap()) {
		if a == 0 {
			continue;
		}
		poly[indices[a]] += 1;
	}
	let mut m = karatsuba(&poly, &poly);
	for (e, co) in poly.iter().enumerate() {
		m[2 * e] -= co;
	}
	let mut ans = 0;
	for (e, co) in m.iter().enumerate() {
		let e = e as i64;
		ans += pows[(e % (P - 1)) as usize] * co / 2;
	}
	println!("{}", ans);
}

use crate::traits::consts::{Bool, False, True};
use std::ops::{Add, Mul, Sub};

pub fn karatsuba<T>(a: &[T], b: &[T]) -> Vec<T>
where
	T: Clone + num::Zero + Sub<Output = T> + Mul<Output = T> + std::fmt::Debug,
	for<'a> &'a T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Add<T, Output = T>,
{
	fn internal<T, Overwrite: Bool>(a: &[T], b: &[T], r: &mut [T], scratch: &mut [T]) -> usize
	where
		T: Clone + num::Zero + Sub<Output = T> + Mul<Output = T> + std::fmt::Debug,
		for<'a> &'a T: Add<Output = T> + Sub<Output = T> + Mul<Output = T> + Add<T, Output = T>,
	{
		let (a, b) = if a.len() <= b.len() { (a, b) } else { (b, a) };
		if a.len() == 0 {
			return 0;
		}
		if b.len() < 24 {
			if Overwrite::VALUE {
				for r in r.iter_mut() {
					*r = T::zero();
				}
			}
			for i in 0..a.len() {
				for j in 0..b.len() {
					unsafe {
						*r.get_unchecked_mut(i + j) =
							r.get_unchecked(i + j) + a.get_unchecked(i) * b.get_unchecked(j);
					}
				}
			}
			a.len() + b.len() - 1
		} else {
			let k = (b.len() + 1) / 2;

			let (sc1, sc2) = scratch.split_at_mut(2 * k);
			let ac = internal::<T, True>(&a[0..std::cmp::min(k, a.len())], &b[0..k], sc1, sc2);
			if Overwrite::VALUE {
				unsafe {
					let l = std::cmp::min(ac, k);
					for i in 0..l {
						*r.get_unchecked_mut(i) = sc1.get_unchecked(i).clone();
						*r.get_unchecked_mut(i + k) = T::zero() - sc1.get_unchecked(i).clone();
					}
					if l == k {
						for i in k..ac {
							*r.get_unchecked_mut(i) = r.get_unchecked(i) + sc1.get_unchecked(i);
							*r.get_unchecked_mut(i + k) = T::zero() - sc1.get_unchecked(i).clone();
						}
					} else {
						for r in r[ac..k].iter_mut() {
							*r = T::zero();
						}
					}
					for r in r[k + ac..3 * k].iter_mut() {
						*r = T::zero();
					}
				}
				let bc = internal::<T, True>(&a[std::cmp::min(k, a.len())..], &b[k..], sc1, sc2);
				unsafe {
					let l = std::cmp::min(bc, k);
					for i in 0..l {
						*r.get_unchecked_mut(i + 2 * k) =
							r.get_unchecked(i + 2 * k) + sc1.get_unchecked(i);
						*r.get_unchecked_mut(i + k) = r.get_unchecked(i + k) - sc1.get_unchecked(i);
					}
					if l == k {
						for i in k..bc {
							*r.get_unchecked_mut(i + 2 * k) = sc1.get_unchecked(i).clone();
							*r.get_unchecked_mut(i + k) =
								r.get_unchecked(i + k) - sc1.get_unchecked(i);
						}
					}
				}
			} else {
				for i in 0..ac {
					unsafe {
						*r.get_unchecked_mut(i) = r.get_unchecked(i) + sc1.get_unchecked(i);
						*r.get_unchecked_mut(i + k) = r.get_unchecked(i + k) - sc1.get_unchecked(i);
					}
				}
				let bc = internal::<T, True>(&a[std::cmp::min(k, a.len())..], &b[k..], sc1, sc2);
				for i in 0..bc {
					unsafe {
						*r.get_unchecked_mut(i + 2 * k) =
							r.get_unchecked(i + 2 * k) + sc1.get_unchecked(i);
						*r.get_unchecked_mut(i + k) = r.get_unchecked(i + k) - sc1.get_unchecked(i);
					}
				}
			}

			unsafe {
				let l = b.len() - k;
				for i in 0..l {
					*scratch.get_unchecked_mut(i) = b.get_unchecked(i) + b.get_unchecked(i + k);
				}
				for (sc, e) in scratch[l..k].iter_mut().zip(b[l..k].iter()) {
					*sc = e.clone();
				}
			}

			if a.len() < k {
				let (src, sc) = scratch.split_at_mut(k);
				internal::<T, False>(a, src, &mut r[k..3 * k], sc);
			} else {
				unsafe {
					let l = a.len() - k;
					for i in 0..l {
						*scratch.get_unchecked_mut(i + k) =
							a.get_unchecked(i) + a.get_unchecked(i + k);
					}
					for (sc, e) in scratch[k + l..2 * k].iter_mut().zip(a[l..k].iter()) {
						*sc = e.clone();
					}
				}

				let (src, sc) = scratch.split_at_mut(2 * k);
				internal::<T, False>(&src[k..], &src[..k], &mut r[k..3 * k], sc);
			}

			a.len() + b.len() - 1
		}
	}
	if a.len() == 0 || b.len() == 0 {
		return Vec::new();
	}
	let n = std::cmp::max(a.len(), b.len()) + std::mem::size_of::<usize>() * 8;
	let mut v = vec![T::zero(); n * 4];
	let (r, scratch) = v.split_at_mut(2 * n);
	internal::<T, False>(a, b, r, scratch);
	v.truncate(a.len() + b.len() - 1);
	v
}

pub mod traits {
	pub mod consts {

		pub trait LiteralConstant {
			type Type;
			const VALUE: Self::Type;
		}

		macro_rules! impl_const {
			($trait:ident ,$struct:ident, $type:ty, $value:expr) => {
				pub struct $struct;
				impl $trait for $struct {}
				impl LiteralConstant for $struct {
					type Type = $type;
					const VALUE: $type = $value;
				}
			};
		}

		pub trait Bool: LiteralConstant<Type = bool> {}
		impl_const![Bool, True, bool, true];
		impl_const![Bool, False, bool, false];
	}
}