#include<iostream>
#include<string>
#include<vector>
#include<algorithm>
#include<bitset>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#include<list>
#include<iomanip>
#include<cmath>
#include<cstring>
#include<functional>
#include<cstdio>
#include<cstdlib>
using namespace std;

#define repr(i, a, b) for (int i = (int)(a); i < (int)(b); i++)
#define rep(i, n) repr(i, 0, n)
#define INF 2e9
#define MOD 1000000007
//#define MOD 998244353
#define LINF (long long)4e18
#define jck 3.141592

const double EPS = 1e-10;

using ll = long long;
using Pi = pair<int,int>;
using Pl = pair<ll,ll>;


int main(){
    int n; cin >> n;
    vector<ll> a(n);
    rep(i,n){
        double b;
        cin >> b;
        b *= 1000000000;
        a[i] = (ll)(b+0.0005);
    }
    map<Pi,int> cnt;
    rep(i,n){
        ll now = a[i];
        int cnt2 = 0;
        while(now%2 == 0){
            cnt2++;
            now /= 2;
        }
        now = a[i];
        int cnt3 = 0;
        while(now%5 == 0){
            cnt3++;
            now /= 5;
        }
        cnt[Pi(cnt2,cnt3)]++;
    }
    ll ans = 0;
    ll ans2 = 0;
    for(auto p1: cnt){
        for(auto p2: cnt){
            if(p1.first.first+p2.first.first >= 18 && p1.first.second+p2.first.second >= 18){
                if(p1 == p2){
                    ans2 += (ll)p1.second*(p1.second-1)/2;
                }
                else ans += (ll)p1.second*p2.second;
            }
        }
    }
    ans = ans/2+ans2;
    cout << ans << endl;
}


#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<vector>
#include<functional>
#include<algorithm>
#include<stdlib.h>
#include<string>
#include<string.h>
#define _USE_MATH_DEFINES
#include<math.h>
#include<deque>
#include<set>
#include<map>
#include<queue>
#include<list>
#include<iostream>
#include <bitset>
using namespace std;
typedef long long ll;
#define rep(i,a,b) for(auto i=a;i<b;i++)
#define all(_x) _x.begin(), _x.end()
#define r_sort(_x) sort(_x.begin(), _x.end(), std::greater<int>())
#define vec_cnt(_a, _n) (upper_bound(all(_a), _n) - lower_bound(all(_a), _n))
#define vec_unique(_a) _a.erase(std::unique(all(_a)), _a.end());
#define vvec vector<vector<ll>>
ll gcd(ll a, ll b) { return a % b == 0 ? b : gcd(b, a % b); }
ll lcm(ll a, ll b) { return (a / gcd(a, b)) * b; }
#define INF 1 << 30
const int mod = 1000000007;
ll power(ll x, ll p) { ll a = 1; while (p > 0) { if (p % 2 == 0) { x *= x; p /= 2; } else { a *= x; p--; } }return a; }
ll mpower(ll x, ll p) { ll a = 1; while (p > 0) { if (p % 2 == 0) { x = x * x % mod; p /= 2; } else { a = a * x % mod; p--; } }return a; }
ll ac(ll n, ll k) { ll a = 1; rep(i, 1, k) { a *= n - i + 1; a /= i; }return a; }
ll mc(ll n, ll m) { ll k = 1, l = 1; rep(i, n - m + 1, n + 1) k = k * i % mod; rep(i, 1, m + 1) l = l * i % mod; l = mpower(l, mod - 2); return k * l % mod; }
struct UnionFind {
	vector<int> par;
	UnionFind(int N) : par(N) { rep(i, 0, N)par[i] = i;}
	int root(int x) { return par[x] == x ? x : par[x] = root(par[x]);}
	void unite(int x, int y) {if (!same(x, y)) par[root(x)] = root(y); }
	bool same(int x, int y) {return root(x) == root(y);}
};
int main()
{
	int H, W;
	ll ans = 0;
	cin >> H >> W;
	vector<string> S(H);
	UnionFind tree(W * H);
	rep(i, 0, H)cin >> S[i];
	rep(i, 0, H) {
		rep(i2, 0, W) {
			if (i != H - 1 && S[i][i2] != S[i + 1][i2]) {
				tree.unite(i * W + i2, i * W + W + i2);
			}
			if (i2 != W - 1 && S[i][i2] != S[i][i2 + 1]) {
				tree.unite(i * W + i2, i * W + 1 + i2);
			}
		}
	}
	map<int, pair<int, int>>mp;
	rep(i, 0, H * W) {
		if(S[i / W][i % W] == '#')mp[tree.root(i)].first++;
		else mp[tree.root(i)].second++;
	}
	for (auto m : mp) {
		ans += (ll)m.second.first * m.second.second;
	}
	printf("%lld\n", ans);
	return 0;
}
