#include <bits/stdc++.h>
using namespace std::literals::string_literals;
using i64 = std::int_fast64_t;
using std::cout;
using std::cerr;
using std::endl;
using std::cin;

template<typename T>
std::vector<T> make_v(size_t a){return std::vector<T>(a);}

template<typename T,typename... Ts>
auto make_v(size_t a,Ts... ts){
  return std::vector<decltype(make_v<T>(ts...))>(a,make_v<T>(ts...));
}

#ifndef INCLUDED_FENWICK_TREE_HPP
#define INCLUDED_FENWICK_TREE_HPP

#include <functional>
#include <vector>

template<class CommutativeMonoid>
class fenwick_tree {
public:
	using T = typename CommutativeMonoid::value_type;
	using size_type = std::uint_fast32_t;

	using checker = std::function<bool(T)>;

	std::vector<T> data;
	
private:
	size_type get_lsb(size_type i) const { return i & (~i + 1); }
	
public:
	fenwick_tree() = default;
	fenwick_tree(const fenwick_tree &) = default;
	fenwick_tree(fenwick_tree &&) = default;

	fenwick_tree(size_type size): data(size + 1, T{}) {}

	template<class InputIt>
	fenwick_tree(InputIt first, InputIt last) : fenwick_tree(std::distance(first, last)) {
		for(int index = 0; first != last; first++, index++) add(index, *first);
	}
	
	fenwick_tree & operator=(const fenwick_tree &) = default;
	fenwick_tree & operator=(fenwick_tree &&) = default;

	T fold(size_type last) const {
		T acc{};
		while(last) {
			acc = CommutativeMonoid::operation(data[last], acc);

			last -= get_lsb(last);
		}
		
		return acc;
	}
	T fold(size_type first, size_type last) const {
		T acc{};
		while(first < last) {
			acc = CommutativeMonoid::operation(data[last], acc);

			last -= get_lsb(last);
		}

		while(last < first) {
			acc = CommutativeMonoid::operation(CommutativeMonoid::inverse(data[first]), acc);

			first -= get_lsb(first);
		}
		
		return acc;
	}
	void update(size_type index, const T& value) {
		for(++index; index < data.size(); index += get_lsb(index)) {
			data[index] = CommutativeMonoid::operation(data[index], value);
		}
	}
	void change(size_type index, const T& value) {
		update(index, CommutativeMonoid::operation(CommutativeMonoid::inverse((*this)[index]), value));
	}

	// min{x | f(fold(x)) = true}
	template<class F>
	size_type search(const F & f) {
		if(f(T{})) return 0;

		T acc{};
		size_type i = 0, k = data.size();
		while(k >>= 1) {
			if((i | k) < data.size() and !f(CommutativeMonoid::operation(acc, data[i | k]))) {
				acc = CommutativeMonoid::operation(acc, data[i | k]);
				i |= k;
			}
		}
		return i + 1;
	}

	T operator[](const size_type& k) const { return fold(k, k + 1); };

	bool empty() const { return size() == 0; }
	size_type size() const { return data.size() - 1; }
	void swap(fenwick_tree & r) { data.swap(r.data); }
};

template<class T>
struct monoid {
	using value_type = T;

	static value_type operation(const value_type& a, const value_type& b) { return a + b; };
	static value_type inverse(const value_type& x) { return -x; }
};

#endif

int main() {
	int n; scanf("%d", &n);

	std::vector<std::pair<int, int>> vec(n);
	for(int i = 0; i < n; i++) {
		std::string s; cin >> s;

		int left = 9;
		for(int i = 0; i < s.size(); i++) {
			if(s[i] != '.') continue;
			left = 9 - (s.size() - (i + 1));
		}
		
		for(int i = 0; i < s.size(); i++) if(s[i] == '.') s.erase(begin(s) + i);
		while(left--) s += '0';
		i64 x = std::stoll(s);

		while(!(x % 2)) {
			vec[i].first++;
			x /= 2;
		}
		while(!(x % 5)) {
			vec[i].second++;
			x /= 5;
		}
	}
	sort(begin(vec), end(vec));

	i64 ans = 0;
	fenwick_tree<monoid<int>> fwt(100);
	for(int i = 0, idx = (int)vec.size() - 1; i < vec.size(); i++) {
		while(idx >= 0 and vec[i].first + vec[idx].first >= 18) {
			fwt.update(vec[idx].second, 1);
			idx--;
		}

		ans += fwt.fold(18 - vec[i].second, 100);
		ans -= (vec[i].first * 2 >= 18 and vec[i].second * 2 >= 18);
	}
	printf("%lld\n", ans / 2);
	return 0;
}


Measured memory_bytes: 4844