Language: C++

#define _CRT_SECURE_NO_WARNINGS
#include <iostream>
#include <sstream>
#include <iomanip>
#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <cctype>
#include <cstring>
#include <vector>
#include <list>
#include <queue>
#include <deque>
#include <stack>
#include <map>
#include <set>
#include <algorithm>
#include <iterator>
#include <bitset>
#include <ctime>
#include<complex>
using namespace std;

#define FOR(i,a,b) for (int i = (a); i < (b); i++)
#define RFOR(i,b,a) for (int i = (b)-1; i >= (a); i--)
#define ITER(it,a) for (__typeof(a.begin()) it = a.begin(); it != a.end(); it++)
#define FILL(a,value) memset(a, value, sizeof(a))

#define SZ(a) (int)a.size()
#define ALL(a) a.begin(), a.end()
#define PB push_back
#define MP make_pair

typedef long long LL;
typedef vector<int> VI;
typedef pair<int, int> PII;

const double PI = acos(-1.0);
const int INF = 1000 * 1000 * 1000 + 7;
const LL LINF = INF * (LL)INF;

const int MAX = 1000 * 100 + 47;
const int MAX1 = MAX * (LL)MAX;

unsigned long long abs(unsigned long long n)
{
	return n;
}

//! Возвращает true, если n четное
template <class T>
bool even(const T & n)
{
	// return n % 2 == 0;
	return (n & 1) == 0;
}

//! Делит число на 2
template <class T>
void bisect(T & n)
{
	// n /= 2;
	n >>= 1;
}

//! Умножает число на 2
template <class T>
void redouble(T & n)
{
	// n *= 2;
	n <<= 1;
}

//! Возвращает true, если n - точный квадрат простого числа
template <class T>
bool perfect_square(const T & n)
{
	T sq = (T)ceil(sqrt((double)n));
	return sq*sq == n;
}

//! Вычисляет корень из числа, округляя его вниз
template <class T>
T sq_root(const T & n)
{
	return (T)floor(sqrt((double)n));
}

//! Возвращает количество бит в числе (т.е. минимальное количество бит, которыми можно представить данное число)
template <class T>
unsigned bits_in_number(T n)
{
	if (n == 0)
		return 1;
	unsigned result = 0;
	while (n)
	{
		bisect(n);
		++result;
	}
	return result;
}

//! Возвращает значение k-го бита числа (биты нумеруются с нуля)
template <class T>
bool test_bit(const T & n, unsigned k)
{
	return (n & (T(1) << k)) != 0;
}

//! Умножает a *= b (mod n)
template <class T>
void mulmod(T & a, T b, const T & n)
{
	// наивная версия, годится только для длинной арифметики
	a *= b;
	a %= n;
}

template <>
void mulmod(int & a, int b, const int & n)
{
	a = int((((long long)a) * b) % n);
}

template <>
void mulmod(unsigned & a, unsigned b, const unsigned & n)
{
	a = unsigned((((unsigned long long)a) * b) % n);
}

template <>
void mulmod(unsigned long long & a, unsigned long long b, const unsigned long long & n)
{
	// сложная версия, основанная на бинарном разложении произведения в сумму
	if (a >= n)
		a %= n;
	if (b >= n)
		b %= n;
	unsigned long long res = 0;
	while (b)
		if (!even(b))
		{
			res += a;
			while (res >= n)
				res -= n;
			--b;
		}
		else
		{
			redouble(a);
			while (a >= n)
				a -= n;
			bisect(b);
		}
	a = res;
}

template <>
void mulmod(long long & a, long long b, const long long & n)
{
	bool neg = false;
	if (a < 0)
	{
		neg = !neg;
		a = -a;
	}
	if (b < 0)
	{
		neg = !neg;
		b = -b;
	}
	unsigned long long aa = a;
	mulmod<unsigned long long>(aa, (unsigned long long)b, (unsigned long long)n);
	a = (long long)aa * (neg ? -1 : 1);
}


//! Вычисляет a^k (mod n). Использует бинарное возведение в степень
template <class T, class T2>
T powmod(T a, T2 k, const T & n)
{
	T res = 1;
	while (k)
		if (!even(k))
		{
			mulmod(res, a, n);
			--k;
		}
		else
		{
			mulmod(a, a, n);
			bisect(k);
		}
	return res;
}

//! Переводит число n в форму q*2^p
template <class T>
void transform_num(T n, T & p, T & q)
{
	T p_res = 0;
	while (even(n))
	{
		++p_res;
		bisect(n);
	}
	p = p_res;
	q = n;
}

//! Алгоритм Евклида
template <class T, class T2>
T gcd(const T & a, const T2 & b)
{
	return (a == 0) ? b : gcd(b % a, a);
}

//! Вычисляет jacobi(a,b)
template <class T>
T jacobi(T a, T b)
{

#pragma warning (push)
#pragma warning (disable: 4146)

	if (a == 0)
		return 0;
	if (a == 1)
		return 1;

	if (a < 0)
		if ((b & 2) == 0)
			return jacobi(-a, b);
		else
			return -jacobi(-a, b);

	T e, a1;
	transform_num(a, e, a1);

	T s;
	if (even(e) || (b & 7) == 1 || (b & 7) == 7)
		s = 1;
	else
		s = -1;
	if ((b & 3) == 3 && (a1 & 3) == 3)
		s = -s;
	if (a1 == 1)
		return s;
	return s * jacobi(b % a1, a1);

#pragma warning (pop)

}

//! Вычисляет pi(b) первых простых чисел. Возвращает ссылку на вектор с простыми (в векторе может оказаться больше простых, чем надо) и в pi - pi(b)
template <class T, class T2>
const std::vector<T> & get_primes(const T & b, T2 & pi)
{

	static std::vector<T> primes;
	static T counted_b;

	// если результат уже был вычислен ранее, возвращаем его, иначе довычисляем простые
	if (counted_b >= b)
		pi = T2(std::upper_bound(primes.begin(), primes.end(), b) - primes.begin());
	else
	{

		// число 2 обрабатываем отдельно
		if (counted_b == 0)
		{
			primes.push_back(2);
			counted_b = 2;
		}

		// теперь обрабатываем все нечётные, пока не наберём нужное количество простых
		T first = counted_b == 2 ? 3 : primes.back() + 2;
		for (T cur = first; cur <= b; ++++cur)
		{
			bool cur_is_prime = true;
			for (std::vector<T>::const_iterator iter = primes.begin(), end = primes.end();
				iter != end; ++iter)
			{
				const T & div = *iter;
				if (div * div > cur)
					break;
				if (cur % div == 0)
				{
					cur_is_prime = false;
					break;
				}
			}
			if (cur_is_prime)
				primes.push_back(cur);
		}

		counted_b = b;
		pi = (T2)primes.size();

	}

	return primes;

}

//! Тривиальная проверка n на простоту, перебираются все делители до m. Результат: 1 - если n точно простое, p - его найденный делитель, 0 - если неизвестно, является ли n простым или нет
template <class T, class T2>
T2 prime_div_trivial(const T & n, T2 m)
{

	// сначала проверяем тривиальные случаи
	if (n == 2 || n == 3)
		return 1;
	if (n < 2)
		return 0;
	if (even(n))
		return 2;

	// генерируем простые от 3 до m
	T2 pi;
	const vector<T2> & primes = get_primes(m, pi);

	// делим на все простые
	for (std::vector<T2>::const_iterator iter = primes.begin(), end = primes.end();
		iter != end; ++iter)
	{
		const T2 & div = *iter;
		if (div * div > n)
			break;
		else
			if (n % div == 0)
				return div;
	}

	if (n < m*m)
		return 1;
	return 0;

}

//! Усиленный алгоритм Миллера-Рабина проверки n на простоту по базису b
template <class T, class T2>
bool miller_rabin(T n, T2 b)
{

	// сначала проверяем тривиальные случаи
	if (n == 2)
		return true;
	if (n < 2 || even(n))
		return false;

	// проверяем, что n и b взаимно просты (иначе это приведет к ошибке)
	// если они не взаимно просты, то либо n не просто, либо нужно увеличить b
	if (b < 2)
		b = 2;
	for (T g; (g = gcd(n, b)) != 1; ++b)
		if (n > g)
			return false;

	// разлагаем n-1 = q*2^p
	T n_1 = n;
	--n_1;
	T p, q;
	transform_num(n_1, p, q);

	// вычисляем b^q mod n, если оно равно 1 или n-1, то n, вероятно, простое
	T rem = powmod(T(b), q, n);
	if (rem == 1 || rem == n_1)
		return true;

	// теперь вычисляем b^2q, b^4q, ... , b^((n-1)/2)
	// если какое-либо из них равно n-1, то n, вероятно, простое
	for (T i = 1; i<p; i++)
	{
		mulmod(rem, rem, n);
		if (rem == n_1)
			return true;
	}

	return false;

}

//! Усиленный алгоритм Лукаса-Селфриджа проверки n на простоту. Используется усиленный алгоритм Лукаса с параметрами Селфриджа. Работает только с знаковыми типами!!! Второй параметр unused не используется, он только дает тип
template <class T, class T2>
bool lucas_selfridge(const T & n, T2 unused)
{

	// сначала проверяем тривиальные случаи
	if (n == 2)
		return true;
	if (n < 2 || even(n))
		return false;

	// проверяем, что n не является точным квадратом, иначе алгоритм даст ошибку
	if (perfect_square(n))
		return false;

	// алгоритм Селфриджа: находим первое число d такое, что:
	// jacobi(d,n)=-1 и оно принадлежит ряду { 5,-7,9,-11,13,... }
	T2 dd;
	for (T2 d_abs = 5, d_sign = 1; ; d_sign = -d_sign, ++++d_abs)
	{
		dd = d_abs * d_sign;
		T g = gcd(n, d_abs);
		if (1 < g && g < n)
			// нашли делитель - d_abs
			return false;
		if (jacobi(T(dd), n) == -1)
			break;
	}

	// параметры Селфриджа
	T2
		p = 1,
		q = (p*p - dd) / 4;

	// разлагаем n+1 = d*2^s
	T n_1 = n;
	++n_1;
	T s, d;
	transform_num(n_1, s, d);

	// алгоритм Лукаса
	T
		u = 1,
		v = p,
		u2m = 1,
		v2m = p,
		qm = q,
		qm2 = q * 2,
		qkd = q;
	for (unsigned bit = 1, bits = bits_in_number(d); bit < bits; bit++)
	{
		mulmod(u2m, v2m, n);
		mulmod(v2m, v2m, n);
		while (v2m < qm2)
			v2m += n;
		v2m -= qm2;
		mulmod(qm, qm, n);
		qm2 = qm;
		redouble(qm2);
		if (test_bit(d, bit))
		{
			T t1, t2;
			t1 = u2m;
			mulmod(t1, v, n);
			t2 = v2m;
			mulmod(t2, u, n);

			T t3, t4;
			t3 = v2m;
			mulmod(t3, v, n);
			t4 = u2m;
			mulmod(t4, u, n);
			mulmod(t4, (T)dd, n);

			u = t1 + t2;
			if (!even(u))
				u += n;
			bisect(u);
			u %= n;

			v = t3 + t4;
			if (!even(v))
				v += n;
			bisect(v);
			v %= n;
			mulmod(qkd, qm, n);
		}
	}

	// точно простое (или псевдо-простое)
	if (u == 0 || v == 0)
		return true;

	// дополнительные проверки, иначе некоторые составные числа "превратятся" в простые
	T qkd2 = qkd;
	redouble(qkd2);
	for (T2 r = 1; r < s; ++r)
	{
		mulmod(v, v, n);
		v -= qkd2;
		if (v < 0) v += n;
		if (v < 0) v += n;
		if (v >= n) v -= n;
		if (v >= n) v -= n;
		if (v == 0)
			return true;
		if (r < s - 1)
		{
			mulmod(qkd, qkd, n);
			qkd2 = qkd;
			redouble(qkd2);
		}
	}

	return false;

}

//! Алгоритм Бэйли-Померанс-Селфридж-Вагстафф (BPSW) проверки n на простоту
template <class T>
bool baillie_pomerance_selfridge_wagstaff(T n)
{

	// сначала проверяем на тривиальные делители - до 29
	int div = prime_div_trivial(n, 29);
	if (div == 1)
		return true;
	if (div > 1)
		return false;
	// если div == 0, то на тривиальные делители n не делится

	// тест Миллера-Рабина по базису 2
	if (!miller_rabin(n, 2))
		return false;

	// усиленный тест Лукаса-Селфриджа
	return lucas_selfridge(n, 0);

}

//! Алгоритм Бэйли-Померанс-Селфридж-Вагстафф (BPSW) проверки n на простоту
template <class T>
bool isprime(T n)
{
	return baillie_pomerance_selfridge_wagstaff(n);
}

//! Метод Полларда p-1 факторизации числа. Функция возвращает найденный делитель числа или 1, если ничего не найдено
template <class T>
T pollard_p_1(T n)
{
	// параметры алгоритма, существенно влияют на производительность и качество поиска
	const T b = 13;
	const T q[] = { 2, 3, 5, 7, 11, 13 };

	// несколько попыток алгоритма
	T a = 5 % n;
	for (int j = 0; j<10; j++)
	{

		// ищем такое a, которое взаимно просто с n
		while (gcd(a, n) != 1)
		{
			mulmod(a, a, n);
			a += 3;
			a %= n;
		}

		// вычисляем a^M
		for (size_t i = 0; i < sizeof q / sizeof q[0]; i++)
		{
			T qq = q[i];
			T e = (T)floor(log((double)b) / log((double)qq));
			T aa = powmod(a, powmod(qq, e, n), n);
			if (aa == 0)
				continue;

			// проверяем, не найден ли ответ
			T g = gcd(aa - 1, n);
			if (1 < g && g < n)
				return g;
		}

	}

	// если ничего не нашли
	return 1;

}

//! Метод Полларда RHO факторизации числа. Возвращает его найденный делитель или 1, если ничего не было найдено
template <class T>
T pollard_rho(T n, unsigned iterations_count = 100000)
{
	T
		b0 = rand() % n,
		b1 = b0,
		g;
	mulmod(b1, b1, n);
	if (++b1 == n)
		b1 = 0;
	g = gcd(abs(b1 - b0), n);
	for (unsigned count = 0; count<iterations_count && (g == 1 || g == n); count++)
	{
		mulmod(b0, b0, n);
		if (++b0 == n)
			b0 = 0;
		mulmod(b1, b1, n);
		++b1;
		mulmod(b1, b1, n);
		if (++b1 == n)
			b1 = 0;
		g = gcd(abs(b1 - b0), n);
	}
	return g;
}

//! Метод Полларда-Бента факторизации числа. Возвращает его найденный делитель или 1, если ничего не было найдено
template <class T>
T pollard_bent(T n, unsigned iterations_count = 19)
{
	T
		b0 = rand() % n,
		b1 = (b0*b0 + 2) % n,
		a = b1;
	for (unsigned iteration = 0, series_len = 1; iteration<iterations_count; iteration++, series_len *= 2)
	{
		T g = gcd(b1 - b0, n);
		for (unsigned len = 0; len<series_len && (g == 1 && g == n); len++)
		{
			b1 = (b1*b1 + 2) % n;
			g = gcd(abs(b1 - b0), n);
		}
		b0 = a;
		a = b1;
		if (g != 1 && g != n)
			return g;
	}
	return 1;
}

//! Метод Полларда Monte-Carlo факторизации числа. Возвращает его найденный делитель или 1, если ничего не было найдено
template <class T>
T pollard_monte_carlo(T n, unsigned m = 100)
{
	T b = rand() % (m - 2) + 2;

	static std::vector<T> primes;
	static T m_max;
	if (primes.empty())
		primes.push_back(3);
	if (m_max < m)
	{
		m_max = m;
		for (T prime = 5; prime <= m; ++++prime)
		{
			bool is_prime = true;
			for (std::vector<T>::const_iterator iter = primes.begin(), end = primes.end();
				iter != end; ++iter)
			{
				T div = *iter;
				if (div*div > prime)
					break;
				if (prime % div == 0)
				{
					is_prime = false;
					break;
				}
			}
			if (is_prime)
				primes.push_back(prime);
		}
	}

	T g = 1;
	for (size_t i = 0; i<primes.size() && g == 1; i++)
	{
		T cur = primes[i];
		while (cur <= n)
			cur *= primes[i];
		cur /= primes[i];
		b = powmod(b, cur, n);
		g = gcd(abs(b - 1), n);
		if (g == n)
			g = 1;
	}

	return g;
}

//! Метод Ферма факторизации числа. Работает в худшем случае за O(sqrt(n)). Возвращает найденный делитель. Второй параметр должен быть того же типа, что и первый, только signed
template <class T, class T2>
T ferma(const T & n, T2 unused)
{
	T2
		x = sq_root(n),
		y = 0,
		r = x*x - y*y - n;
	for (;;)
		if (r == 0)
			return x != y ? x - y : x + y;
		else
			if (r > 0)
			{
				r -= y + y + 1;
				++y;
			}
			else
			{
				r += x + x + 1;
				++x;
			}
}

//! Рекурсивная факторизация числа. Последний параметр должен быть того же типа, что и первый, только signed. Использует тест BPSW, метод Ферма, метод Полларда RHO, метод Полларда-Бента, метод Полларда Monte-Carlo
template <class T, class T2>
void factorize(const T & n, std::map<T, unsigned> & result, T2 unused)
{
	if (n == 1)
		;
	else
		// проверяем, не простое ли число
		if (isprime(n))
			++result[n];
		else
			// если число достаточно маленькое, то его разлагаем простым перебором
			if (n < 1000 * 1000)
			{
				T div = prime_div_trivial(n, 1000);
				++result[div];
				factorize(n / div, result, unused);
			}
			else
			{
				// число большое, запускаем на нем алгоритмы факторизации
				T div;
				// сначала идут быстрые алгоритмы Полларда
				div = pollard_monte_carlo(n);
				if (div == 1)
					div = pollard_rho(n);
				if (div == 1)
					div = pollard_p_1(n);
				if (div == 1)
					div = pollard_bent(n);
				// если алгоритмы Полларда ничего не дали, то запускаем алгоритм Ферма, который гарантированно находит делитель
				if (div == 1)
					div = ferma(n, unused);
				// рекурсивно обрабатываем найденные множители
				factorize(div, result, unused);
				factorize(n / div, result, unused);
			}
}

LL A[MAX];
int P[MAX];
LL L[MAX];
int sz;
pair<LL, LL> E[MAX];
int esz;
map<LL, int> mapp;

pair<LL,LL> get(LL a)
{
	LL r1 = 1;
	LL r2 = 1;
	typedef long long base;

	base n;
	cin >> n;

	map <base, unsigned> mapp;
	//cout << a << ":" << endl;
	factorize(a, mapp, (long long)0);

	for (map <base, unsigned>::iterator i = mapp.begin(); i != mapp.end(); ++i)
	{
		LL p = i->first;
		int cnt = i->second % 3;
		//cout << p << " " << cnt << endl;
		cnt %= 3;
		FOR(k, 0, cnt) r1 *= p;
		cnt = (cnt * 2) % 3;

		FOR(k, 0, cnt)
		{
			if (r2 >= MAX1) continue;
			r2 *= p;
		}
	}

	return MP(r1, r2);
}

int main()
{
	//freopen("in.txt", "r", stdin);
	//freopen("out.txt", "w", stdout);
	ios::sync_with_stdio(false); cin.tie(0);
	FOR(i, 2, MAX)
	{
		if (!P[i])
		{
			L[sz++] = i;
			int j = i;
			while (j < MAX)
			{
				if (P[j] == 0) P[j] = i;
				j += i;
			}
		}
	}

	int n;
	cin >> n;
	FOR(i, 0, n)
	{
		cin >> A[i];
	}

	int ans = 0;
	FOR(i, 0, n)
	{
		E[i] = get(A[i]);
		mapp[E[i].first]++;
		//cout << "??" << A[i] << endl;
		
	}

	sort(E, E + n);

	LL tmp = 0;
	FOR(i, 0, n)
	{
		if (i && E[i] == E[i - 1]) continue;
		int a = E[i].first;
		int b = E[i].second;

		//	cout << a << " " << b << " " << mapp[a] << " " << mapp[b] << endl;
		if (a == 1)
		{
			ans++;
			continue;
		}

		int cnt1 = mapp[a];
		int cnt2 = mapp[b];
		if (cnt1 > cnt2)
		{
			ans += cnt1;
			continue;
		}

		if (cnt1 == cnt2) tmp += cnt1;
	}

	cout << ans + tmp / 2 << endl;
}

Compiler output:
a.cc:43:22: warning: overflow in conversion from 'LL' {aka 'long long int'} to 'int' changes value from '10009402209' to '1419467617' [-Woverflow]
   43 | const int MAX1 = MAX * (LL)MAX;
      |                  ~~~~^~~~~~~~~
a.cc: In function 'const std::vector<_Tp>& get_primes(const T&, T2&)':
a.cc:282:30: error: need 'typename' before 'std::vector<_Tp>::const_iterator' because 'std::vector<_Tp>' is a dependent scope
  282 |                         for (std::vector<T>::const_iterator iter = primes.begin(), end = primes.end();
      |                              ^~~
a.cc:282:60: error: expected ';' before 'iter'
  282 |                         for (std::vector<T>::const_iterator iter = primes.begin(), end = primes.end();
      |                                                            ^~~~~
      |                                                            ;
a.cc:283:33: error: 'iter' was not declared in this scope
  283 |                                 iter != end; ++iter)
      |                                 ^~~~
a.cc: In function 'T2 prime_div_trivial(const T&, T2)':
a.cc:325:14: error: need 'typename' before 'std::vector<_ValT>::const_iterator' because 'std::vector<_ValT>' is a dependent scope
  325 |         for (std::vector<T2>::const_iterator iter = primes.begin(), end = primes.end();
      |              ^~~
a.cc:325:45: error: expected ';' before 'iter'
  325 |         for (std::vector<T2>::const_iterator iter = primes.begin(), end = primes.end();
      |                                             ^~~~~
      |                                             ;
a.cc:326:17: error: 'iter' was not declared in this scope
  326 |                 iter != end; ++iter)
      |                 ^~~~
a.cc: In function 'T pollard_monte_carlo(T, unsigned int)':
a.cc:642:30: error: need 'typename' before 'std::vector<_Tp>::const_iterator' because 'std::vector<_Tp>' is a dependent scope
  642 |                         for (std::vector<T>::const_iterator iter = primes.begin(), end = primes.end();
      |                              ^~~
a.cc:642:60: error: expected ';' before 'iter'
  642 |                         for (std::vector<T>::const_iterator iter = primes.begin(), end = primes.end();
      |                                                            ^~~~~
      |                                                            ;
a.cc:643:33: error: 'iter' was not declared in this scope
  643 |                                 iter != end; ++iter)
      |                                 ^~~~
a.cc: In instantiation of 'T2 prime_div_trivial(const T&, T2) [with T = long long int; T2 = int]':
a.cc:713:30:   required from 'void factorize(const T&, std::map<T, unsigned int>&, T2) [with T = long long int; T2 = long long int]'
  713 |                                 T div = prime_div_trivial(n, 1000);
      |                                         ~~~~~~~~~~~~~~~~~^~~~~~~~~
a.cc:757:11:   required from here
  757 |         factorize(a, mapp, (long long)0);
      |         ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
a.cc:325:31: error: dependent-name 'std::vector<_ValT>::const_iterator' is parsed as a non-type, but instantiation yields a type
  325 |         for (std::vector<T2>::const_iterator iter = primes.begin(), end = primes.end();
      |                               ^~~~~~~~~~~~~~
a.cc:325:31: note: say 'typename std::vector<_ValT>::const_iterator' if a type is meant
a.cc: In instantiation of 'T pollard_monte_carlo(T, unsigned int) [with T = long long int]':
a.cc:722:30:   required from 'void factorize(const T&, std::map<T, unsigned int>&, T2) [with T = long long int; T2 = long long int]'
  722 |                                 div = pollard_monte_carlo(n);
      |                                       ~~~~~~~~~~~~~~~~~~~^~~
a.cc:757:11:   required from here
  757 |         factorize(a, mapp, (long long)0);
      |         ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
a.cc:642:46: error: dependent-name 'std::vector<_Tp>::const_iterator' is parsed as a non-type, but instantiation yields a type
  642 |                         for (std::vector<T>::const_iterator iter = primes.begin(), end = primes.end();
      |                                              ^~~~~~~~~~~~~~
a.cc:642:46: note: say 'typename std::vector<_Tp>::const_iterator' if a type is meant
a.cc: In instantiation of 'const std::vector<_Tp>& get_primes(const T&, T2&) [with T = int; T2 = int]':
a.cc:322:40:   required from 'T2 prime_div_trivial(const T&, T2) [with T = long long int; T2 = int]'
  322 |         const vector<T2> & primes = get_primes(m, pi);
      |                                     ~~~~~~~~~~^~~~~~~
a.cc:713:30:   required from 'void factorize(const T&, std::map<T, unsigned int>&, T2) [with T = long long int; T2 = long long int]'
  713 |                                 T div = prime_div_trivial(n, 1000);
      |                                         ~~~~~~~~~~~~~~~~~^~~~~~~~~
a.cc:757:11:   required from here
  757 |         factorize(a, mapp, (long long)0);
      |         ~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~
a.cc:282:46: error: dependent-name 'std::vector<_Tp>::const_iterator' is parsed as a non-type, but instantiation yields a type
  282 |                         for (std::vector<T>::const_iterator iter = primes.begin(), end = primes.end();
      |                                              ^~~~~~~~~~~~~~
a.cc:282:46: note: say 'typename std::vector<_Tp>::const_iterator' if a type is meant