#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    vector<long long> dpl, dpr, a, st, ans1, ans2;
    long long n, maxi, maxii;
    cin >> n;
    dpl.resize(n);
    dpr.resize(n);
    a.resize(n);
    ans1.assign(n, 0);
    ans2.assign(n, 0);
    st.push_back(-1);
    for (int i = 0; i < n; i ++) cin >> a[i];
    for (int i = 0; i < n; i ++) {
        while (st.size() != 1 && a[i] <= a[st[st.size()-1]]) {
            st.pop_back();
        }
        dpl[i] = st[st.size()-1];
        st.push_back(i);
    }
    //for (int i = 0; i < n; i ++) cout << dpl[i] << " ";
    //cout << endl;
    st.resize(1);
    st[0] = -1;
    for (int i = n-1; i >-1; i --) {
        while (st.size() != 1 && a[i] <= a[st[st.size()-1]]) {
            st.pop_back();
        }
        dpr[i] = st[st.size()-1];
        st.push_back(i);
    }
    //for (int i = 0; i < n; i ++) cout << dpr[i] << " ";
    for (int i = 0; i < n; i ++) {
        if (dpl[i] != -1) {
            ans1[i] = ans1[dpl[i]]+a[i]*(i-dpl[i]);
        }
        else {
            ans1[i] = a[i]*(i+1);
        }
    }
    for (int i = n-1; i > -1; i --) {
        if (dpr[i] != -1) {
            ans2[i] = ans2[dpr[i]]+a[i]*(dpr[i]-i+1);
        }
        else {
            ans2[i] = a[i]*(n-i);
        }
    }
    maxi = -1;
    maxii = 0;
    for (int i = 0; i < n; i ++) {
        if ((ans1[i]+ans2[i]) > maxi) {
            maxi = ans1[i]+ans2[i];
            maxii = i;
        }
    }
    //cout << maxii << endl;
    for (int i = maxii + 1; i < n; i ++) {
        a[i] = min(a[i], a[i-1]);
    }
    for (int i = maxii - 1; i > -1; i --) {
        a[i] = min(a[i], a[i+1]);
    }
    for (int i = 0; i < n; i ++) cout << a[i] << " ";
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    vector<long long> dpl, dpr, a, st, ans1, ans2;
    int n, maxi, maxii;
    cin >> n;
    dpl.resize(n);
    dpr.resize(n);
    a.resize(n);
    ans1.assign(n, 0);
    ans2.assign(n, 0);
    st.push_back(-1);
    for (int i = 0; i < n; i ++) cin >> a[i];
    for (int i = 0; i < n; i ++) {
        while (st.size() != 1 && a[i] < a[st[st.size()-1]]) {
            st.pop_back();
        }
        dpl[i] = st[st.size()-1];
        st.push_back(i);
    }
    //for (int i = 0; i < n; i ++) cout << dpl[i] << " ";
    //cout << endl;
    st.resize(1);
    st[0] = -1;
    for (int i = n-1; i >-1; i --) {
        while (st.size() != 1 && a[i] < a[st[st.size()-1]]) {
            st.pop_back();
        }
        dpr[i] = st[st.size()-1];
        st.push_back(i);
    }
    //for (int i = 0; i < n; i ++) cout << dpr[i] << " ";
    for (int i = 0; i < n; i ++) {
        if (dpl[i] != -1) {
            ans1[i] = ans1[dpl[i]]+a[i]*(i-dpl[i]);
        }
        else {
            ans1[i] = a[i]*(i+1);
        }
    }
    for (int i = n-1; i > -1; i --) {
        if (dpr[i] != -1) {
            ans2[i] = ans2[dpr[i]]+a[i]*(dpr[i]-i);
        }
        else {
            ans2[i] = a[i]*(n-i+1);
        }
    }
    maxi = -1;
    maxii = 0;
    for (int i = 0; i < n; i ++) {
        if ((ans1[i]+ans2[i]) > maxi) {
            maxi = ans1[i]+ans2[i];
            maxii = i;
        }
    }
    //cout << maxii << endl;
    for (int i = maxii + 1; i < n; i ++) {
        a[i] = min(a[i], a[i-1]);
    }
    for (int i = maxii - 1; i > -1; i --) {
        a[i] = min(a[i], a[i+1]);
    }
    for (int i = 0; i < n; i ++) cout << a[i] << " ";
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    long long n, e, b=0;
    vector<long long> m, s, mr, ml, r, l;
    cin >> n;
    r.resize(n);
    l.resize(n);
    for (int i = 0; i<n; i++){
        cin >> e;
        m.push_back(e);
        mr.push_back(n);
        ml.push_back(-1);
    }
    for (int i = 0; i < n; i++) {
        while (s.size() > 0 && m[s[s.size()-1]] > m[i]) {
            mr[s[s.size()-1]] = i;
            s.pop_back();
        }
        s.push_back(i);
    }
    s.resize(0);
    for (int i = n-1; i > -1; i--) {
        while (s.size() > 0 && m[s[s.size()-1]] > m[i]) {
            ml[s[s.size()-1]] = i;
            s.pop_back();
        }
        s.push_back(i);
    }
    for (int i = 0; i<n; i++) {
        if (ml[i] == -1) l[i] = (i+1)*m[i];
            else l[i] = l[ml[i]] + (i-ml[i]) * m[i];
    }
    for (int i = n-1; i>-1; i--) {
        if (mr[i] == n) r[i] = (n-i)*m[i];
            else r[i] = r[mr[i]] + (mr[i]-i) * m[i];
    }
    for (int i = 1; i<n; i++) {
        if (l[i]+r[i]-m[i] > l[b]+r[b]-m[b]) b = i;
    }
    for (int i = b + 1; i < n; i++) m[i] = min(m[i], m[i-1]);
    for (int i = b - 1; i > -1; i --) m[i] = min(m[i], m[i+1]);
    for (int i = 0; i<n; i++) cout << m[i] << " ";
}


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    vector<long long> dpl, dpr, a, st, ans1, ans2;
    long long n, maxi, maxii;
    cin >> n;
    dpl.resize(n);
    dpr.resize(n);
    a.resize(n);
    ans1.assign(n, 0);
    ans2.assign(n, 0);
    st.push_back(-1);
    for (int i = 0; i < n; i ++) cin >> a[i];
    for (int i = 0; i < n; i ++) {
        while (st.size() != 1 && a[i] < a[st[st.size()-1]]) {
            st.pop_back();
        }
        dpl[i] = st[st.size()-1];
        st.push_back(i);
    }
    //for (int i = 0; i < n; i ++) cout << dpl[i] << " ";
    //cout << endl;
    st.resize(1);
    st[0] = -1;
    for (int i = n-1; i >-1; i --) {
        while (st.size() != 1 && a[i] < a[st[st.size()-1]]) {
            st.pop_back();
        }
        dpr[i] = st[st.size()-1];
        st.push_back(i);
    }
    //for (int i = 0; i < n; i ++) cout << dpr[i] << " ";
    for (int i = 0; i < n; i ++) {
        if (dpl[i] != -1) {
            ans1[i] = ans1[dpl[i]]+a[i]*(i-dpl[i]);
        }
        else {
            ans1[i] = a[i]*(i+1);
        }
    }
    for (int i = n-1; i > -1; i --) {
        if (dpr[i] != -1) {
            ans2[i] = ans2[dpr[i]]+a[i]*(dpr[i]-i);
        }
        else {
            ans2[i] = a[i]*(n-i);
        }
    }
    maxi = -1;
    maxii = 0;
    for (int i = 0; i < n; i ++) {
        if ((ans1[i]+ans2[i]) > maxi) {
            maxi = ans1[i]+ans2[i];
            maxii = i;
        }
    }
    //cout << maxii << endl;
    for (int i = maxii + 1; i < n; i ++) {
        a[i] = min(a[i], a[i-1]);
    }
    for (int i = maxii - 1; i > -1; i --) {
        a[i] = min(a[i], a[i+1]);
    }
    for (int i = 0; i < n; i ++) cout << a[i] << " ";
    return 0;
}


#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
int main()
{
    vector<long long> dpl, dpr, a, st, ans1, ans2;
    long long n, maxi, maxii;
    cin >> n;
    dpl.resize(n);
    dpr.resize(n);
    a.resize(n);
    ans1.assign(n, 0);
    ans2.assign(n, 0);
    st.push_back(-1);
    for (int i = 0; i < n; i ++) cin >> a[i];
    for (int i = 0; i < n; i ++) {
        while (st.size() != 1 && a[i] < a[st[st.size()-1]]) {
            st.pop_back();
        }
        dpl[i] = st[st.size()-1];
        st.push_back(i);
    }
    //for (int i = 0; i < n; i ++) cout << dpl[i] << " ";
    //cout << endl;
    st.resize(1);
    st[0] = -1;
    for (int i = n-1; i >-1; i --) {
        while (st.size() != 1 && a[i] < a[st[st.size()-1]]) {
            st.pop_back();
        }
        dpr[i] = st[st.size()-1];
        st.push_back(i);
    }
    //for (int i = 0; i < n; i ++) cout << dpr[i] << " ";
    for (int i = 0; i < n; i ++) {
        if (dpl[i] != -1) {
            ans1[i] = ans1[dpl[i]]+a[i]*(i-dpl[i]);
        }
        else {
            ans1[i] = a[i]*(i+1);
        }
    }
    for (int i = n-1; i > -1; i --) {
        if (dpr[i] != -1) {
            ans2[i] = ans2[dpr[i]]+a[i]*(dpr[i]-i);
        }
        else {
            ans2[i] = a[i]*(n-i+1);
        }
    }
    maxi = -1;
    maxii = 0;
    for (int i = 0; i < n; i ++) {
        if ((ans1[i]+ans2[i]) > maxi) {
            maxi = ans1[i]+ans2[i];
            maxii = i;
        }
    }
    //cout << maxii << endl;
    for (int i = maxii + 1; i < n; i ++) {
        a[i] = min(a[i], a[i-1]);
    }
    for (int i = maxii - 1; i > -1; i --) {
        a[i] = min(a[i], a[i+1]);
    }
    for (int i = 0; i < n; i ++) cout << a[i] << " ";
    return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pb push_back
#define PI 3.14159265
#define pii pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

ll dpl[500005],dpr[500005],m[500005],a[500005];
set<int> d;
map<int,int> g;

int main()
{
	fast;
	int n;
	cin >> n;
	for(int i=1;i<=n;i++)
	cin >> m[i];
	dpl[1]=m[1];
	d.insert(m[1]);
	g[m[1]]=1;
	for(int i=2;i<=n;i++)
	{
		auto it=d.lower_bound(m[i]);
		if(it!=d.begin())
		{
			it--;
			dpl[i]=dpl[g[*it]]+(i-g[*it])*m[i];
		}
		else dpl[i]=i*m[i];
		d.insert(m[i]);
		g[m[i]]=i;
	}
	d.clear();
	g.clear();
	dpr[n]=m[n];
	d.insert(m[n]);
	g[m[n]]=n;
	for(int i=n-1;i>=1;i--)
	{
		auto it=d.lower_bound(m[i]);
		if(it!=d.begin())
		{
			it--;
			dpr[i]=dpr[g[*it]]+(g[*it]-i)*m[i];
		}
		else dpr[i]=(n-i+1)*m[i];
		d.insert(m[i]);
		g[m[i]]=i;
	}
	int ansi=1;
	for(int i=2;i<=n;i++)
	if(dpl[i]+dpr[i]-m[i]>dpl[ansi]+dpr[ansi]-m[ansi]) ansi=i;
	a[ansi]=m[ansi];
	for(int i=ansi-1;i>=1;i--)
	a[i]=min(a[i+1],m[i]);
	for(int i=ansi+1;i<=n;i++)
	a[i]=min(a[i-1],m[i]);
	for(int i=1;i<=n;i++)
	cout<<a[i]<<" ";

	return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pb push_back
#define PI 3.14159265
#define pii pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

ll dpl[500005],dpr[500005],m[500005],a[500005];

int main()
{
	fast;
	int t=1;
	//cin >> t;
	while(t--)
	{
		set<ll> mp;
		map<ll,ll> g;
		int n;
		cin >> n;
		for(int i=0;i<n;i++)
			cin >> m[i];
		dpl[0]=m[0];
		mp.insert(-m[0]);
		g[m[0]]=0;
		for(ll i=1;i<n;i++)
		{
				if(-m[i]<=*mp.rbegin())
				dpl[i]=dpl[g[-*mp.lower_bound(-m[i])]]+(i-g[-*mp.lower_bound(-m[i])])*m[i];
				else dpl[i]=m[i]*(i+1);
				mp.insert(-m[i]);
				g[m[i]]=i;

		}
		g.clear();
		mp.clear();
		dpr[n-1]=m[n-1];
		g[m[n-1]]=n-1;
		mp.insert(-m[n-1]);
		for(ll i=n-2;i>=0;i--)
		{
				if(-m[i]<=*mp.rbegin())
				dpr[i]=dpr[g[-*mp.lower_bound(-m[i])]]+(g[-*mp.lower_bound(-m[i])]-i)*m[i];
				else dpr[i]=m[i]*(n-i);
				mp.insert(-m[i]);
				g[m[i]]=i;

		}
		int ansi=0;
		for(int i=1;i<n;i++)
		if(dpl[i]+dpr[i]-m[i]>dpl[ansi]+dpr[ansi]-m[ansi]) ansi=i;
		a[ansi]=m[ansi];
		for(int i=ansi-1;i>=0;i--)
			a[i]=min(a[i+1],m[i]);
		for(int i=ansi+1;i<n;i++)
			a[i]=min(a[i-1],m[i]);
		for(int i=0;i<n;i++)
		cout<<a[i]<<" ";

	}

	return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pb push_back
#define PI 3.14159265
#define pii pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

int dpl[500005],dpr[500005],m[500005],a[500005];

int main()
{
	fast;
	int t=1;
	//cin >> t;
	while(t--)
	{
		set<int> mp;
		map<int,int> g;
		int n;
		cin >> n;
		for(int i=0;i<n;i++)
			cin >> m[i];
		dpl[0]=m[0];
		mp.insert(-m[0]);
		g[m[0]]=0;
		for(int i=1;i<n;i++)
		{
			if(m[i]>m[i-1])
			dpl[i]=dpl[i-1]+m[i];
			else
			{
				if(mp.lower_bound(-m[i])!=mp.end())
				dpl[i]=dpl[g[-*mp.lower_bound(-m[i])]]+(i-g[-*mp.lower_bound(-m[i])])*m[i];
				else dpl[i]=m[i]*(i+1);
				mp.insert(-m[i]);
				g[m[i]]=i;
			}
		}
		g.clear();
		mp.clear();
		dpr[n-1]=m[n-1];
		g[m[n-1]]=n-1;
		mp.insert(-m[n-1]);
		for(int i=n-2;i>=0;i--)
		{
			if(m[i]>m[i+1])
			dpr[i]=dpr[i+1]+m[i];
			else
			{
				if(mp.lower_bound(-m[i])!=mp.end())
				dpr[i]=dpr[g[-*mp.lower_bound(-m[i])]]+(g[-*mp.lower_bound(-m[i])]-i)*m[i];
				else dpr[i]=m[i]*(n-i);
				mp.insert(-m[i]);
				g[m[i]]=i;
			}
		}
		int ansi=0;
		for(int i=1;i<n;i++)
		if(dpl[i]+dpr[i]-m[i]>dpl[ansi]+dpr[ansi]-m[ansi]) ansi=i;
		a[ansi]=m[ansi];
		for(int i=ansi-1;i>=0;i--)
			a[i]=min(a[i+1],m[i]);
		for(int i=ansi+1;i<n;i++)
			a[i]=min(a[i-1],m[i]);
		for(int i=0;i<n;i++)
		cout<<a[i]<<" ";

	}

	return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pb push_back
#define PI 3.14159265
#define pii pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

ll dpl[500005],dpr[500005],m[500005],a[500005],l[50005],r[50005];
set<int> d;
map<int,int> g;

int main()
{
	fast;
	int n;
	cin >> n;
	for(int i=1;i<=n;i++)
	cin >> m[i];

	dpl[1]=m[1];
	for(int i=2;i<=n;i++)
	{
		int j=i-1;
		while(j&&m[j]>m[i]) j=l[j];
		l[i]=j;
		dpl[i]=dpl[j]+ll(i-j)*m[i];
	}
	dpr[n]=m[n];
	r[n]=n+1;
	for(int i=n-1;i>=1;i--)
	{
		int j=i+1;
		while(j<=n&&m[j]>m[i]) j=r[j];
		r[i]=j;
		dpr[i]=dpr[j]+ll(j-i)*m[i];
	}

	int ansi=1;
	for(int i=2;i<=n;i++)
	if(dpl[i]+dpr[i]-m[i]>dpl[ansi]+dpr[ansi]-m[ansi]) ansi=i;
	a[ansi]=m[ansi];
	for(int i=ansi-1;i>=1;i--)
	a[i]=min(a[i+1],m[i]);
	for(int i=ansi+1;i<=n;i++)
	a[i]=min(a[i-1],m[i]);
	for(int i=1;i<=n;i++)
	cout<<a[i]<<" ";
	return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pb push_back
#define PI 3.14159265
#define pii pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

ll dpl[500005],dpr[500005],m[500005],a[500005];
set<int> d;
map<int,int> g;

int main()
{
	fast;
	int n;
	cin >> n;
	for(int i=1;i<=n;i++)
	cin >> m[i];
	dpl[1]=m[1];
	d.insert(m[1]);
	g[m[1]]=1;
	for(int i=2;i<=n;i++)
	{
		auto it=d.upper_bound(m[i]);
		if(it!=d.begin())
		{
			it--;
			dpl[i]=dpl[g[*it]]+(i-g[*it])*m[i];
		}
		else dpl[i]=i*m[i];
		d.insert(m[i]);
		g[m[i]]=i;
	}
	d.clear();
	g.clear();
	dpr[n]=m[n];
	d.insert(m[n]);
	g[m[n]]=n;
	for(int i=n-1;i>=1;i--)
	{
		auto it=d.upper_bound(m[i]);
		if(it!=d.begin())
		{
			it--;
			dpr[i]=dpr[g[*it]]+(g[*it]-i)*m[i];
		}
		else dpr[i]=(n-i+1)*m[i];
		d.insert(m[i]);
		g[m[i]]=i;
	}
	int ansi=1;
	for(int i=2;i<=n;i++)
	if(dpl[i]+dpr[i]-m[i]>dpl[ansi]+dpr[ansi]-m[ansi]) ansi=i;
	a[ansi]=m[ansi];
	for(int i=ansi-1;i>=1;i--)
	a[i]=min(a[i+1],m[i]);
	for(int i=ansi+1;i<=n;i++)
	a[i]=min(a[i-1],m[i]);
	for(int i=1;i<=n;i++)
	cout<<a[i]<<" ";

	return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pb push_back
#define PI 3.14159265
#define pii pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

ll dpl[500005],dpr[500005],m[500005],a[500005];

int main()
{
	fast;
	int t=1;
	//cin >> t;
	while(t--)
	{
		set<ll> mp;
		map<ll,ll> g;
		int n;
		cin >> n;
		for(int i=0;i<n;i++)
			cin >> m[i];
		dpl[0]=m[0];
		mp.insert(-m[0]);
		g[m[0]]=0;
		for(int i=1;i<n;i++)
		{
			if(m[i]>m[i-1])
			dpl[i]=dpl[i-1]+m[i];
			else
			{
				if(-m[i]<=*mp.rbegin())
				dpl[i]=dpl[g[-*mp.lower_bound(-m[i])]]+(i-g[-*mp.lower_bound(-m[i])])*m[i];
				else dpl[i]=m[i]*(i+1);
				mp.insert(-m[i]);
				g[m[i]]=i;
			}
		}
		g.clear();
		mp.clear();
		dpr[n-1]=m[n-1];
		g[m[n-1]]=n-1;
		mp.insert(-m[n-1]);
		for(int i=n-2;i>=0;i--)
		{
			if(m[i]>m[i+1])
			dpr[i]=dpr[i+1]+m[i];
			else
			{
				if(-m[i]<=*mp.rbegin())
				dpr[i]=dpr[g[-*mp.lower_bound(-m[i])]]+(g[-*mp.lower_bound(-m[i])]-i)*m[i];
				else dpr[i]=m[i]*(n-i);
				mp.insert(-m[i]);
				g[m[i]]=i;
			}
		}
		int ansi=0;
		for(int i=1;i<n;i++)
		if(dpl[i]+dpr[i]-m[i]>dpl[ansi]+dpr[ansi]-m[ansi]) ansi=i;
		a[ansi]=m[ansi];
		for(int i=ansi-1;i>=0;i--)
			a[i]=min(a[i+1],m[i]);
		for(int i=ansi+1;i<n;i++)
			a[i]=min(a[i-1],m[i]);
		for(int i=0;i<n;i++)
		cout<<a[i]<<" ";

	}

	return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pb push_back
#define PI 3.14159265
#define pii pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

ll dpl[500005],dpr[500005],m[500005],a[500005];

int main()
{
	fast;
	int t=1;
	//cin >> t;
	while(t--)
	{
		set<ll> mp;
		map<ll,ll> g;
		int n;
		cin >> n;
		for(int i=0;i<n;i++)
			cin >> m[i];
		dpl[0]=m[0];
		mp.insert(-m[0]);
		g[m[0]]=0;
		for(int i=1;i<n;i++)
		{
				if(-m[i]<=*mp.rbegin())
				dpl[i]=dpl[g[-*mp.lower_bound(-m[i])]]+(i-g[-*mp.lower_bound(-m[i])])*m[i];
				else dpl[i]=m[i]*(i+1);
				mp.insert(-m[i]);
				g[m[i]]=i;

		}
		g.clear();
		mp.clear();
		dpr[n-1]=m[n-1];
		g[m[n-1]]=n-1;
		mp.insert(-m[n-1]);
		for(int i=n-2;i>=0;i--)
		{

				if(-m[i]<=*mp.rbegin())
				dpr[i]=dpr[g[-*mp.lower_bound(-m[i])]]+(g[-*mp.lower_bound(-m[i])]-i)*m[i];
				else dpr[i]=m[i]*(n-i);
				mp.insert(-m[i]);
				g[m[i]]=i;

		}
		int ansi=0;
		for(int i=1;i<n;i++)
		if(dpl[i]+dpr[i]-m[i]>dpl[ansi]+dpr[ansi]-m[ansi]) ansi=i;
		a[ansi]=m[ansi];
		for(int i=ansi-1;i>=0;i--)
			a[i]=min(a[i+1],m[i]);
		for(int i=ansi+1;i<n;i++)
			a[i]=min(a[i-1],m[i]);
		for(int i=0;i<n;i++)
		cout<<a[i]<<" ";

	}

	return 0;
}


#include<bits/stdc++.h>
using namespace std;

#define fast ios_base::sync_with_stdio(false);cin.tie(nullptr);cout.tie(nullptr);
#define pb push_back
#define PI 3.14159265
#define pii pair<int,int>
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;

int dpl[500005],dpr[500005],m[500005],a[500005];

int main()
{
	fast;
	int t=1;
	//cin >> t;
	while(t--)
	{
		set<int> mp;
		map<int,int> g;
		int n;
		cin >> n;
		for(int i=0;i<n;i++)
			cin >> m[i];
		dpl[0]=m[0];
		mp.insert(-m[0]);
		g[m[0]]=0;
		for(int i=1;i<n;i++)
		{
			if(m[i]>m[i-1])
			dpl[i]=dpl[i-1]+m[i];
			else
			{
				if(-m[i]<=*mp.rbegin())
				dpl[i]=dpl[g[-*mp.lower_bound(-m[i])]]+(i-g[-*mp.lower_bound(-m[i])])*m[i];
				else dpl[i]=m[i]*(i+1);
				mp.insert(-m[i]);
				g[m[i]]=i;
			}
		}
		g.clear();
		mp.clear();
		dpr[n-1]=m[n-1];
		g[m[n-1]]=n-1;
		mp.insert(-m[n-1]);
		for(int i=n-2;i>=0;i--)
		{
			if(m[i]>m[i+1])
			dpr[i]=dpr[i+1]+m[i];
			else
			{
				if(-m[i]<=*mp.rbegin())
				dpr[i]=dpr[g[-*mp.lower_bound(-m[i])]]+(g[-*mp.lower_bound(-m[i])]-i)*m[i];
				else dpr[i]=m[i]*(n-i);
				mp.insert(-m[i]);
				g[m[i]]=i;
			}
		}
		int ansi=0;
		for(int i=1;i<n;i++)
		if(dpl[i]+dpr[i]-m[i]>dpl[ansi]+dpr[ansi]-m[ansi]) ansi=i;
		a[ansi]=m[ansi];
		for(int i=ansi-1;i>=0;i--)
			a[i]=min(a[i+1],m[i]);
		for(int i=ansi+1;i<n;i++)
			a[i]=min(a[i-1],m[i]);
		for(int i=0;i<n;i++)
		cout<<a[i]<<" ";

	}

	return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<string>
using namespace std;

const int maxn = 500000 + 10;

int a[maxn];
stack<pair<int,int>> s;
int pre[maxn], beh[maxn];
long long s_pre[maxn], s_beh[maxn];
long long ans[maxn] = { 0 };

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	for (int i = 1; i <= n; i++)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != 1) pre[i] = s.empty() ? i : s.top().second;
		s_pre[i] = s_pre[pre[i]] + 1ll * (i - pre[i] + pre[i]==i) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	while (s.size()) s.pop();
	beh[n] = n + 1;
	for (int i = n; i >= 1; i--)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != n) beh[i] = s.empty() ? i:s.top().second;
		s_beh[i] = s_beh[beh[i]] + 1ll * (beh[i] - i+beh[i]==i) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	long long max_val = -1, max_index;
	for (int i = 1; i <= n; i++)
		if (s_pre[i] + s_beh[i] - a[i] > max_val)
			max_val = s_pre[i] + s_beh[i] - a[i], max_index = i;

	ans[max_index] = a[max_index];
	for (int i = max_index - 1; i >= 1; i--)
		ans[i] = min((long long)a[i], ans[i + 1]);
	for (int i = max_index + 1; i <= n; i++)
		ans[i] = min((long long)a[i], ans[i - 1]);

	for (int i = 1; i <= n; i++)
		cout << ans[i] << " ";
}

int main()
{
	//freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<string>
using namespace std;

const int maxn = 500000 + 10;

int a[maxn];
stack<pair<int,int>> s;
int pre[maxn], beh[maxn];
long long s_pre[maxn], s_beh[maxn];
long long ans[maxn] = { 0 };

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	for (int i = 1; i <= n; i++)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != 1) pre[i] = s.empty() ? i : s.top().second;
		s_pre[i] = s_pre[pre[i]] + 1ll * (i - pre[i]) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	while (s.size()) s.pop();
	beh[n] = n + 1;
	for (int i = n; i >= 1; i--)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != n) beh[i] = s.empty() ? i:s.top().second;
		s_beh[i] = s_beh[beh[i]] + 1ll * (beh[i] - i) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	long long max_val = -1, max_index;
	for (int i = 1; i <= n; i++)
		if (s_pre[i] + s_beh[i] - a[i] > max_val)
			max_val = s_pre[i] + s_beh[i] - a[i], max_index = i;

	cout << max_val << endl;;

	ans[max_index] = a[max_index];
	for (int i = max_index - 1; i >= 1; i--)
		ans[i] = min((long long)a[i], ans[i + 1]);
	for (int i = max_index + 1; i <= n; i++)
		ans[i] = min((long long)a[i], ans[i - 1]);

	for (int i = 1; i <= n; i++)
		cout << ans[i] << " ";
}

int main()
{
	//freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<string>
using namespace std;

const int maxn = 500000 + 10;

int a[maxn];
stack<pair<int,int>> s;
int pre[maxn], beh[maxn];
long long s_pre[maxn], s_beh[maxn];
long long ans[maxn] = { 0 };

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	for (int i = 1; i <= n; i++)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != 1) pre[i] = s.empty() ? i : s.top().second;
		s_pre[i] = s_pre[pre[i]] + 1ll * (i - pre[i] + (pre[i]==i)) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	while (s.size()) s.pop();
	beh[n] = n + 1;
	for (int i = n; i >= 1; i--)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != n) beh[i] = s.empty() ? i:s.top().second;
		s_beh[i] = s_beh[beh[i]] + 1ll * (beh[i] - i+(beh[i]==i)) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	long long max_val = -1, max_index;
	for (int i = 1; i <= n; i++)
		if (s_pre[i] + s_beh[i] - a[i] > max_val)
			max_val = s_pre[i] + s_beh[i] - a[i], max_index = i;

	ans[max_index] = a[max_index];
	for (int i = max_index - 1; i >= 1; i--)
		ans[i] = min((long long)a[i], ans[i + 1]);
	for (int i = max_index + 1; i <= n; i++)
		ans[i] = min((long long)a[i], ans[i - 1]);

	for (int i = 1; i <= n; i++)
		cout << ans[i] << " ";
}

int main()
{
	//freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<string>
using namespace std;

const int maxn = 500000 + 10;

int a[maxn];
stack<pair<int,int>> s;
int pre[maxn], beh[maxn];
long long s_pre[maxn], s_beh[maxn];
long long ans[maxn] = { 0 };

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	for (int i = 1; i <= n; i++)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != 1) pre[i] = s.empty() ? i : s.top().second;
		s_pre[i] = s_pre[pre[i]] + 1ll * (i - pre[i]) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	while (s.size()) s.pop();
	beh[n] = n + 1;
	for (int i = n; i >= 1; i--)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != n) beh[i] = s.empty() ? i:s.top().second;
		s_beh[i] = s_beh[beh[i]] + 1ll * (beh[i] - i) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	long long max_val = -1, max_index;
	for (int i = 1; i <= n; i++)
		if (s_pre[i] + s_beh[i] - a[i] > max_val)
			max_val = s_pre[i] + s_beh[i] - a[i], max_index = i;

	ans[max_index] = a[max_index];
	for (int i = max_index - 1; i >= 1; i--)
		ans[i] = min((long long)a[i], ans[i + 1]);
	for (int i = max_index + 1; i <= n; i++)
		ans[i] = min((long long)a[i], ans[i - 1]);

	for (int i = 1; i <= n; i++)
		cout << ans[i] << " ";
}

int main()
{
	//freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<string>
using namespace std;

const int maxn = 500000 + 10;

int a[maxn];
stack<pair<int,int>> s;
int pre[maxn], beh[maxn];
long long s_pre[maxn], s_beh[maxn];
long long ans[maxn];

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	for (int i = 1; i <= n; i++)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != 1) pre[i] = s.empty() ? 0 : s.top().second;
		s_pre[i] = s_pre[pre[i]] + 1ll * (i - pre[i] ) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	while (s.size()) s.pop();
	beh[n] = n + 1;
	for (int i = n; i >= 1; i--)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != n) beh[i] = s.empty() ? n+1:s.top().second;
		s_beh[i] = s_beh[beh[i]] + 1ll * (beh[i] - i) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	long long max_val = -1, max_index;
	for (int i = 1; i <= n; i++)
		if (s_pre[i] + s_beh[i] - a[i] > max_val)
			max_val = s_pre[i] + s_beh[i] - a[i], max_index = i;

	ans[max_index] = a[max_index];
	for (int i = max_index - 1; i >= 1; i--)
		ans[i] = min((long long)a[i], ans[i + 1]);
	for (int i = max_index + 1; i <= n; i++)
		ans[i] = min((long long)a[i], ans[i - 1]);

	for (int i = 1; i <= n; i++)
		cout << ans[i] << " ";
}

int main()
{
	//freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<string>
using namespace std;

const int maxn = 500000 + 10;

int a[maxn];
stack<pair<int,int>> s;
int pre[maxn], beh[maxn];
long long s_pre[maxn], s_beh[maxn];
long long ans[maxn];

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	for (int i = 1; i <= n; i++)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != 1) pre[i] = s.empty() ? 0 : s.top().second;
		s_pre[i] = s_pre[pre[i]] + 1ll * (i - pre[i] ) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	while (s.size()) s.pop();
	beh[n] = n + 1;
	for (int i = n; i >= 1; i--)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != n) beh[i] = s.empty() ? n+1:s.top().second;
		s_beh[i] = s_beh[beh[i]] + 1ll * (beh[i] - i) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	long long max_val = -1, max_index;
	for (int i = 1; i <= n; i++)
		if (s_pre[i] + s_beh[i] - a[i] > max_val)
			max_val = s_pre[i] + s_beh[i] - a[i], max_index = i;

	ans[max_index] = a[max_index];
	for (int i = max_index - 1; i >= 1; i--)
		ans[i] = min((long long)a[i], ans[i + 1]);
	for (int i = max_index + 1; i <= n; i++)
		ans[i] = min((long long)a[i], ans[i - 1]);

	for (int i = 1; i <= n; i++)
		cout << ans[i] << " ";
}

int main()
{
	freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<stack>
#include<string>
using namespace std;

const int maxn = 500000 + 10;

int a[maxn];
stack<pair<int,int>> s;
int pre[maxn], beh[maxn];
long long s_pre[maxn], s_beh[maxn];
long long ans[maxn] = { 0 };

void solve()
{
	int n;
	cin >> n;
	for (int i = 1; i <= n; i++)
		scanf("%d", &a[i]);

	for (int i = 1; i <= n; i++)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != 1) pre[i] = s.empty() ? 0 : s.top().second;
		s_pre[i] = s_pre[pre[i]] + 1ll * (i - pre[i] ) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	while (s.size()) s.pop();
	beh[n] = n + 1;
	for (int i = n; i >= 1; i--)
	{
		while (!s.empty() && a[i] < s.top().first)
			s.pop();
		if (i != n) beh[i] = s.empty() ? n:s.top().second;
		s_beh[i] = s_beh[beh[i]] + 1ll * (beh[i] - i) * a[i];
		s.push(pair<int, int>(a[i], i));
	}

	long long max_val = -1, max_index;
	for (int i = 1; i <= n; i++)
		if (s_pre[i] + s_beh[i] - a[i] > max_val)
			max_val = s_pre[i] + s_beh[i] - a[i], max_index = i;

	ans[max_index] = a[max_index];
	for (int i = max_index - 1; i >= 1; i--)
		ans[i] = min((long long)a[i], ans[i + 1]);
	for (int i = max_index + 1; i <= n; i++)
		ans[i] = min((long long)a[i], ans[i - 1]);

	for (int i = 1; i <= n; i++)
		cout << ans[i] << " ";
}

int main()
{
	//freopen("Testin.txt", "r", stdin);
	solve();
	return 0;
}


using System;
using System.Linq;
using System.Collections.Generic;
using System.Diagnostics;
using Debug = System.Diagnostics.Trace;
using SB = System.Text.StringBuilder;
using static System.Math;
using Number = System.Int32;

namespace Program {
	public class Solver {
		Random rnd = new Random();
		public void Solve() {
			var n = ri;
			var mod = rl;
			var a = Enumerate(n, x => rl);
			var b = a.ToArray();
			var ids = Enumerate(15, x => new List<int>());
			for (int i = 0; i < n; i++)
				ids[a[i].ToString().Length].Add(i);
			var ans = 0L;
			for (int l = 0; l < 15; l++) {
				var dic = new Dictionary<long, int>();
				foreach (var x in b) if (dic.ContainsKey(x % mod)) dic[x % mod]++;
					else dic[x % mod] = 1;
				foreach (var id in ids[l]) {
					var v = mod - (a[id] % mod);
					if (v == mod) v = 0;
					if (dic.ContainsKey(v)) ans += dic[v];
				}
				for (int i = 0; i < n; i++) b[i] = b[i] * 10 % mod;
			}
			for (int i = 0; i < n; i++) {
				var v = long.Parse(a[i].ToString() + a[i].ToString());
				if (v % mod == 0) ans--;
			}
			Console.WriteLine(ans);

		}

		const long INF = 1L << 60;
		static int[] dx = { -1, 0, 1, 0 };
		static int[] dy = { 0, 1, 0, -1 };
		int ri { get { return sc.Integer(); } }
		long rl { get { return sc.Long(); } }
		double rd { get { return sc.Double(); } }
		string rs { get { return sc.Scan(); } }
		public IO.StreamScanner sc = new IO.StreamScanner(Console.OpenStandardInput());

		static T[] Enumerate<T>(int n, Func<int, T> f) {
			var a = new T[n];
			for (int i = 0; i < a.Length; ++i) a[i] = f(i);
			return a;
		}
		static public void Swap<T>(ref T a, ref T b) { var tmp = a; a = b; b = tmp; }
	}
}

#region main
static class Ex {
	static public string AsString(this IEnumerable<char> ie) { return new string(ie.ToArray()); }
	static public string AsJoinedString<T>(this IEnumerable<T> ie, string st = " ") {
		return string.Join(st, ie);
	}
	static public void Main() {
		Console.SetOut(new Program.IO.Printer(Console.OpenStandardOutput()) { AutoFlush = true });
		var solver = new Program.Solver();
		//*
		var t = new System.Threading.Thread(solver.Solve, 50000000);
		t.Start();
		t.Join();
		//*/
		// solver.Solve();
		Console.Out.Flush();
	}
}
#endregion
#region Ex
namespace Program.IO {
	using System.IO;
	using System.Text;
	using System.Globalization;

	public class Printer : StreamWriter {
		public override IFormatProvider FormatProvider { get { return CultureInfo.InvariantCulture; } }
		public Printer(Stream stream) : base(stream, new UTF8Encoding(false, true)) { }
	}

	public class StreamScanner {
		public StreamScanner(Stream stream) { str = stream; }

		public readonly Stream str;
		private readonly byte[] buf = new byte[1024];
		private int len, ptr;
		public bool isEof = false;
		public bool IsEndOfStream { get { return isEof; } }

		private byte read() {
			if (isEof) return 0;
			if (ptr >= len) {
				ptr = 0;
				if ((len = str.Read(buf, 0, 1024)) <= 0) {
					isEof = true;
					return 0;
				}
			}
			return buf[ptr++];
		}

		public char Char() {
			byte b = 0;
			do b = read(); while ((b < 33 || 126 < b) && !isEof);
			return (char)b;
		}
		public string Scan() {
			var sb = new StringBuilder();
			for (var b = Char(); b >= 33 && b <= 126; b = (char)read()) sb.Append(b);
			return sb.ToString();
		}
		public string ScanLine() {
			var sb = new StringBuilder();
			for (var b = Char(); b != '\n' && b != 0; b = (char)read()) if (b != '\r') sb.Append(b);
			return sb.ToString();
		}
		public long Long() { return isEof ? long.MinValue : long.Parse(Scan()); }
		public int Integer() { return isEof ? int.MinValue : int.Parse(Scan()); }
		public double Double() { return isEof ? double.NaN : double.Parse(Scan(), CultureInfo.InvariantCulture); }
	}
}

#endregion


using System;
using System.Linq;
using CompLib.Util;
using System.Threading;
using System.Collections.Generic;

public class Program
{

    public void Solve()
    {
        var sc = new Scanner();
        int n = sc.NextInt();
        int k = sc.NextInt();
        int[] a = sc.IntArray();

        /*
         * a_i, a_jの連結がkで割り切れる
         *
         * (i,j)のペアの個数
         */

        var map = new Dictionary<Tuple<long, long, int>, Tuple<long, long>>();
        for (int i = 0; i < n; i++)
        {
            int m = a[i] % k;
            {

                int o = m == 0 ? 0 : k - m;
                var key = new Tuple<long, long, int>(o, m, a[i].ToString().Length);

                Tuple<long, long> tmp;
                if (!map.TryGetValue(key, out tmp)) tmp = new Tuple<long, long>(0, 0);
                map[key] = new Tuple<long, long>(tmp.Item1, tmp.Item2 + 1);
            }
            for (int len = 1; len <= 10; len++)
            {
                m *= 10;
                m %= k;

                int o = m == 0 ? 0 : k - m;
                var key = new Tuple<long, long, int>(m, o, len);
                Tuple<long, long> tmp;
                if (!map.TryGetValue(key, out tmp)) tmp = new Tuple<long, long>(0, 0);
                map[key] = new Tuple<long, long>(tmp.Item1 + 1, tmp.Item2);
            }
        }

        long ans = 0;
        foreach (var pair in map)
        {
            ans += pair.Value.Item1 * pair.Value.Item2;
        }

        for (int i = 0; i < n; i++)
        {
            if (long.Parse(a[i].ToString() + a[i].ToString()) % k == 0) ans--;
        }

        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
    // public static void Main(string[] args) => new Thread(new Program().Solve, 1 << 27).Start();
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Linq;
using CompLib.Collections;
using CompLib.Util;

public class Program
{
    int N;
    long K;
    long[] A;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        K = sc.NextInt();
        A = sc.LongArray();

        // ずらす桁数、余り 数
        var map = new HashMap<long, int>[11];
        for (int i = 1; i <= 10; i++)
        {
            map[i] = new HashMap<long, int>();
        }
        foreach (var i in A)
        {
            int p;
            long d;
            for (p = 1, d = 10; p <= 10; p++, d *= 10)
            {
                map[p][(i * d) % K]++;
            }
        }
        long ans = 0;
        foreach (var i in A)
        {
            string str = i.ToString();
            if (i % K == 0) ans += map[str.Length][0];
            else ans += map[str.Length][K - i % K];
            if (long.Parse(str + str) % K == 0) ans--;
        }
        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
}

namespace CompLib.Collections
{
    using System.Collections.Generic;
    public class HashMap<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get
            {
                TValue o;
                return TryGetValue(key, out o) ? o : default(TValue);
            }
            set { base[key] = value; }
        }
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            while (_index >= _line.Length)
            {
                _line = Console.ReadLine().Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Linq;
using CompLib.Collections;
using CompLib.Util;

public class Program
{
    int N;
    long K;
    long[] A;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        K = sc.NextInt();
        A = sc.LongArray();

        // ずらす桁数、余り 数
        var map = new HashMap<long, int>[11];
        for (int i = 1; i <= 10; i++)
        {
            map[i] = new HashMap<long, int>();
        }
        foreach (var i in A)
        {
            int p;
            long d;
            for (p = 1, d = 10; p <= 10; p++, d *= 10)
            {
                d %= K;
                map[p][(i * d) % K]++;
            }
        }
        long ans = 0;
        foreach (var i in A)
        {
            string str = i.ToString();
            if (i % K == 0) ans += map[str.Length][0];
            else ans += map[str.Length][K - i % K];
            if (long.Parse(str + str) % K == 0) ans--;
        }
        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
}

namespace CompLib.Collections
{
    using System.Collections.Generic;
    public class HashMap<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get
            {
                TValue o;
                return TryGetValue(key, out o) ? o : default(TValue);
            }
            set { base[key] = value; }
        }
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            while (_index >= _line.Length)
            {
                _line = Console.ReadLine().Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Linq;
using CompLib.Util;
using System.Threading;
using System.Collections.Generic;
using CompLib.Collections;
public class Program
{

    public void Solve()
    {
        var sc = new Scanner();
        int n = sc.NextInt();
        int k = sc.NextInt();
        int[] a = sc.IntArray();
        /*
         * a_i, a_jの連結がkで割り切れる
         *
         * (i,j)のペアの個数
         */

        var map = new HashMap<(long m, int len), long>();

        foreach (var i in a)
        {
            long m = i % k;
            for (int len = 1; len <= 10; len++)
            {
                m *= 10;
                m %= k;
                map[(m, len)]++;
            }
        }

        long ans = 0;

        foreach (var i in a)
        {
            int m = i % k;
            int o = m == 0 ? 0 : k - m;
            string str = i.ToString();
            ans += map[(o, str.Length)];

            for (int j = 0; j < str.Length; j++)
            {
                m *= 10;
                m += str[j] - '0';
                m %= k;
            }

            if (m == 0) ans--;
        }

        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
    // public static void Main(string[] args) => new Thread(new Program().Solve, 1 << 27).Start();
}

namespace CompLib.Collections
{
    using System.Collections.Generic;
    public class HashMap<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get
            {
                TValue o;
                return TryGetValue(key, out o) ? o : default(TValue);
            }
            set { base[key] = value; }
        }
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Linq;
using CompLib.Collections;
using CompLib.Util;

public class Program
{
    int N;
    long K;
    long[] A;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        K = sc.NextInt();
        A = sc.LongArray();
        Console.WriteLine("-1");
        return;
        // ずらす桁数、余り 数
        var map = new HashMap<long, int>[11];
        for (int i = 1; i <= 10; i++)
        {
            map[i] = new HashMap<long, int>();
        }
        foreach (var i in A)
        {
            int p;
            long d;
            for (p = 1, d = 10; p <= 10; p++, d *= 10)
            {
                d %= K;
                map[p][(i * d) % K]++;
            }
        }
        long ans = 0;
        foreach (var i in A)
        {
            string str = i.ToString();
            if (i % K == 0) ans += map[str.Length][0];
            else ans += map[str.Length][K - i % K];
            if (long.Parse(str + str) % K == 0) ans--;
        }
        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
}

namespace CompLib.Collections
{
    using System.Collections.Generic;
    public class HashMap<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get
            {
                TValue o;
                return TryGetValue(key, out o) ? o : default(TValue);
            }
            set { base[key] = value; }
        }
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            while (_index >= _line.Length)
            {
                _line = Console.ReadLine().Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Linq;
using CompLib.Util;
using System.Threading;
using System.Collections.Generic;

public class Program
{

    public void Solve()
    {
        var sc = new Scanner();
        int n = sc.NextInt();
        int k = sc.NextInt();
        int[] a = sc.IntArray();

        /*
         * a_i, a_jの連結がkで割り切れる
         *
         * (i,j)のペアの個数
         */

        var map = new Dictionary<(int i, int j, int len), (int, int)>();
        for (int i = 0; i < n; i++)
        {
            int m = a[i] % k;
            {

                int o = m == 0 ? 0 : k - m;
                var key = (o, m, a[i].ToString().Length);

                (int, int) tmp;
                if (!map.TryGetValue(key, out tmp)) tmp = (0, 0);
                map[key] = (tmp.Item1, tmp.Item2 + 1);
            }
            for (int len = 1; len <= 10; len++)
            {
                m *= 10;
                m %= k;

                int o = m == 0 ? 0 : k - m;
                var key = (m, o, len);
                (int, int) tmp;
                if (!map.TryGetValue(key, out tmp)) tmp = (0, 0);
                map[key] = (tmp.Item1 + 1, tmp.Item2);
            }
        }

        long ans = 0;
        foreach (var pair in map)
        {
            ans += (long)pair.Value.Item1 * pair.Value.Item2;
        }

        for (int i = 0; i < n; i++)
        {
            if (long.Parse(a[i].ToString() + a[i].ToString()) % k == 0) ans--;
        }

        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
    // public static void Main(string[] args) => new Thread(new Program().Solve, 1 << 27).Start();
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            if (_index >= _line.Length)
            {
                string s;
                do
                {
                    s = Console.ReadLine();
                } while (s.Length == 0);

                _line = s.Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public string ReadLine()
        {
            _index = _line.Length;
            return Console.ReadLine();
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            string s = Console.ReadLine();
            _line = s.Length == 0 ? new string[0] : s.Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Linq;
using CompLib.Collections;
using CompLib.Util;

public class Program
{
    int N;
    long K;
    long[] A;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        K = sc.NextInt();
        A = sc.LongArray();
        // ずらす桁数、余り 数
        var map = new HashMap<long, int>[21];
        for (int i = 0; i <= 20; i++)
        {
            map[i] = new HashMap<long, int>();
        }
        foreach (var i in A)
        {
            long d = 10;
            for (int p = 1; p <= 20; p++)
            {
                map[p][(i * d) % K]++;
                d *= 10;
                d %= K;
            }
        }
        long ans = 0;
        foreach (var i in A)
        {
            string str = i.ToString();
            if (i % K == 0) ans += map[str.Length][0];
            else ans += map[str.Length][K - i % K];
            if (long.Parse(str + str) % K == 0) ans--;
        }
        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
}

namespace CompLib.Collections
{
    using System.Collections.Generic;
    public class HashMap<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get
            {
                TValue o;
                return TryGetValue(key, out o) ? o : default(TValue);
            }
            set { base[key] = value; }
        }
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            while (_index >= _line.Length)
            {
                _line = Console.ReadLine().Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Linq;
using CompLib.Collections;
using CompLib.Util;

public class Program
{
    int N;
    long K;
    long[] A;
    public void Solve()
    {
        var sc = new Scanner();
        N = sc.NextInt();
        K = sc.NextInt();
        A = sc.LongArray();

        var pp = new long[11];
        pp[0] = 1;
        for (int i = 1; i <= 10; i++)
        {
            pp[i] = pp[i - 1] * 10;
            pp[i] %= K;
        }
        // ずらす桁数、余り 数
        var map = new HashMap<long, int>[11];
        for (int i = 0; i <= 10; i++)
        {
            map[i] = new HashMap<long, int>();
        }
        foreach (var i in A)
        {
            long d = 10;
            for (int p = 1; p <= 10; p++)
            {
                map[p][(i * d) % K]++;
                d *= 10;
                d %= K;
            }
        }

        long ans = 0;
        foreach (var i in A)
        {
            string str = i.ToString();
            if (i % K == 0) ans += map[str.Length][0];
            else ans += map[str.Length][K - i % K];
            if ((pp[str.Length] * i + i) % K == 0) ans--;
        }
        Console.WriteLine(ans);
    }

    public static void Main(string[] args) => new Program().Solve();
}

namespace CompLib.Collections
{
    using System.Collections.Generic;
    public class HashMap<TKey, TValue> : Dictionary<TKey, TValue>
    {
        public new TValue this[TKey key]
        {
            get
            {
                TValue o;
                return TryGetValue(key, out o) ? o : default(TValue);
            }
            set { base[key] = value; }
        }
    }
}

namespace CompLib.Util
{
    using System;
    using System.Linq;

    class Scanner
    {
        private string[] _line;
        private int _index;
        private const char Separator = ' ';

        public Scanner()
        {
            _line = new string[0];
            _index = 0;
        }

        public string Next()
        {
            while (_index >= _line.Length)
            {
                _line = Console.ReadLine().Split(Separator);
                _index = 0;
            }

            return _line[_index++];
        }

        public int NextInt() => int.Parse(Next());
        public long NextLong() => long.Parse(Next());
        public double NextDouble() => double.Parse(Next());
        public decimal NextDecimal() => decimal.Parse(Next());
        public char NextChar() => Next()[0];
        public char[] NextCharArray() => Next().ToCharArray();

        public string[] Array()
        {
            _line = Console.ReadLine().Split(Separator);
            _index = _line.Length;
            return _line;
        }

        public int[] IntArray() => Array().Select(int.Parse).ToArray();
        public long[] LongArray() => Array().Select(long.Parse).ToArray();
        public double[] DoubleArray() => Array().Select(double.Parse).ToArray();
        public decimal[] DecimalArray() => Array().Select(decimal.Parse).ToArray();
    }
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace cf_r506_div3_d
{
	internal class Program
	{
		private static readonly long[] factors =
		{
			10,
			100,
			1000,
			10000,
			100000,
			1000000,
			10000000,
			100000000,
			1000000000,
			10000000000
		};

		private static void Main(string[] args)
		{
			var mod = long.Parse(ReadWords()[1]);
			var strNumbers = ReadWords();
			var numbers = new long[strNumbers.Length];
			var numbersWithDigit = new List<long>[factors.Length];
			for (var i = 0; i < numbersWithDigit.Length; i++) numbersWithDigit[i] = new List<long>();

			for (var i = 0; i < strNumbers.Length; i++)
			{
				numbers[i] = long.Parse(strNumbers[i]);
				numbersWithDigit[strNumbers[i].Length - 1].Add(numbers[i] % mod);
			}

			var groupedNumbers = Array.ConvertAll(numbersWithDigit, element =>
				element
					.GroupBy(c => c)
					.Select(g => new KeyValuePair<long, int>(g.Key, g.Count()))
					.ToArray());

			foreach (var group in groupedNumbers) Array.Sort(group, (f, s) => f.Key.CompareTo(s.Key));

			Console.WriteLine(numbers
				.Select((number, i) =>
					FindRightPartCount(number, mod, groupedNumbers, strNumbers[i].Length))
				.Sum());
		}

		private static string[] ReadWords()
		{
			return Console.ReadLine()?.Split(' ') ?? throw new NotImplementedException();
		}

		private static long FindRightPartCount(long number,
			long mod,
			KeyValuePair<long, int>[][] numbersWithDigit,
			int length)
		{
			var sum = 0L;

			for (var i = 0; i < numbersWithDigit.Length; i++)
			{
				var remainder = (mod - number * factors[i] % mod) % mod;
				sum += CountNumbers(remainder, numbersWithDigit[i]);
				if (i == length - 1 && remainder == number % mod) sum--;
			}

			return sum;
		}

		private static long CountNumbers(long remainder, KeyValuePair<long, int>[] group)
		{
			var i = Array.BinarySearch(group,
				new KeyValuePair<long, int>(remainder, 0),
				ReverseComparer.Singleton);
			return i >= 0 ? group[i].Value : 0;
		}
	}

	internal class ReverseComparer : IComparer<KeyValuePair<long, int>>
	{
		public static readonly ReverseComparer Singleton = new ReverseComparer();

		private ReverseComparer()
		{
		}

		public int Compare(KeyValuePair<long, int> f, KeyValuePair<long, int> s)
		{
			return f.Key.CompareTo(s.Key);
		}
	}
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace cf_r506_div3_d
{
	internal class Program
	{
		private static readonly long[] factors =
		{
			10,
			100,
			1000,
			10000,
			100000,
			1000000,
			10000000,
			100000000,
			1000000000,
			10000000000
		};

		private static void Main(string[] args)
		{
			var mod = long.Parse(ReadWords()[1]);
			for (var i = 0; i < factors.Length; i++) factors[i] %= mod;
			var strNumbers = ReadWords();
			var numbers = new long[strNumbers.Length];
			var numbersWithDigit = new List<long>[factors.Length];
			for (var i = 0; i < numbersWithDigit.Length; i++) numbersWithDigit[i] = new List<long>();

			for (var i = 0; i < strNumbers.Length; i++)
			{
				numbers[i] = long.Parse(strNumbers[i]);
				numbersWithDigit[strNumbers[i].Length - 1].Add(numbers[i] % mod);
			}

			var groupedNumbers = Array.ConvertAll(numbersWithDigit, element =>
				element
					.GroupBy(c => c)
					.Select(g => new KeyValuePair<long, int>(g.Key, g.Count()))
					.ToArray());

			foreach (var group in groupedNumbers) Array.Sort(group, (f, s) => f.Key.CompareTo(s.Key));

			Console.WriteLine(numbers
				.Select((number, i) =>
					FindRightPartCount(number, mod, groupedNumbers, strNumbers[i].Length))
				.Sum());
		}

		private static string[] ReadWords()
		{
			return Console.ReadLine()?.Split(' ') ?? throw new NotImplementedException();
		}

		private static long FindRightPartCount(long number,
			long mod,
			KeyValuePair<long, int>[][] numbersWithDigit,
			int length)
		{
			var sum = 0L;

			for (var i = 0; i < numbersWithDigit.Length; i++)
			{
				var remainder = (mod - number * factors[i] % mod) % mod;
				sum += CountNumbers(remainder, numbersWithDigit[i]);
				if (i == length - 1 && remainder == number % mod) sum--;
			}

			return sum;
		}

		private static long CountNumbers(long remainder, KeyValuePair<long, int>[] group)
		{
			var i = Array.BinarySearch(group,
				new KeyValuePair<long, int>(remainder, 0),
				ReverseComparer.Singleton);
			return i >= 0 ? group[i].Value : 0;
		}
	}

	internal class ReverseComparer : IComparer<KeyValuePair<long, int>>
	{
		public static readonly ReverseComparer Singleton = new ReverseComparer();

		private ReverseComparer()
		{
		}

		public int Compare(KeyValuePair<long, int> f, KeyValuePair<long, int> s)
		{
			return f.Key.CompareTo(s.Key);
		}
	}
}


using System;
using System.Collections.Generic;
using System.Linq;

namespace cf_r506_div3_d
{
	internal class Program
	{
		private static readonly long[] factors =
		{
			10,
			100,
			1000,
			10000,
			100000,
			1000000,
			10000000,
			100000000,
			1000000000
		};

		private static void Main(string[] args)
		{
			var mod = long.Parse(ReadWords()[1]);
			var strNumbers = ReadWords();
			var numbers = new long[strNumbers.Length];
			var numbersWithDigit = new List<long>[factors.Length];
			for (var i = 0; i < numbersWithDigit.Length; i++) numbersWithDigit[i] = new List<long>();

			for (var i = 0; i < strNumbers.Length; i++)
			{
				numbers[i] = long.Parse(strNumbers[i]);
				numbersWithDigit[strNumbers[i].Length - 1].Add(numbers[i] % mod);
			}

			var groupedNumbers = Array.ConvertAll(numbersWithDigit, element =>
				element
					.GroupBy(c => c)
					.Select(g => new KeyValuePair<long, int>(g.Key, g.Count()))
					.ToArray());

			foreach (var group in groupedNumbers) Array.Sort(group, (f, s) => f.Key.CompareTo(s.Key));

			Console.WriteLine(numbers
				.Select((number, i) =>
					FindRightPartCount(number, mod, groupedNumbers, strNumbers[i].Length))
				.Sum());
		}

		private static string[] ReadWords()
		{
			return Console.ReadLine()?.Split(' ') ?? throw new NotImplementedException();
		}

		private static long FindRightPartCount(long number,
			long mod,
			KeyValuePair<long, int>[][] numbersWithDigit,
			int length)
		{
			var sum = 0L;

			for (var i = 0; i < numbersWithDigit.Length; i++)
			{
				var remainder = (mod - number * factors[i] % mod) % mod;
				sum += CountNumbers(remainder, numbersWithDigit[i]);
				if (i == length - 1 && remainder == number % mod) sum--;
			}

			return sum;
		}

		private static long CountNumbers(long remainder, KeyValuePair<long, int>[] group)
		{
			var i = Array.BinarySearch(group,
				new KeyValuePair<long, int>(remainder, 0),
				ReverseComparer.Singleton);
			return i >= 0 ? group[i].Value : 0;
		}
	}

	internal class ReverseComparer : IComparer<KeyValuePair<long, int>>
	{
		public static readonly ReverseComparer Singleton = new ReverseComparer();

		private ReverseComparer()
		{
		}

		public int Compare(KeyValuePair<long, int> f, KeyValuePair<long, int> s)
		{
			return f.Key.CompareTo(s.Key);
		}
	}
}


using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
	public static void Main()
	{
		var nk = Console.ReadLine().Split().Select(ulong.Parse).ToArray();
		var n = nk[0];
		var k = nk[1];

		var Z = new Dictionary<ulong, ulong>[11];
		for (var p = 0; p < Z.Length; p++)
			Z[p] = new Dictionary<ulong, ulong>();

		var A = new ulong[n];
		var lens = new int[n];

		var i = 0;
		foreach (var astr in Console.ReadLine().Split())
		{
			var a = ulong.Parse(astr);
			A[i] = a;
			lens[i] = astr.Length;
			var dict = Z[astr.Length];
			if (!dict.ContainsKey(a % k))
				dict[a % k] = 0;
			dict[a % k]++;
			i++;
		}

		var cnt = (ulong)0;
		for (var j = 0ul; j < n; j++)
		{
			for (var p = 1; p < Z.Length; p++)
			{
				var rem = (k - (A[j] * (ulong)Math.Pow(10, p)) % k) % k;
				ulong cp = 0;
				if (!Z[p].TryGetValue(rem, out cp)) cp = 0;

				if (lens[j] == p && rem == A[j] % k)
					cp--;

				cnt += cp;
			}
		}

		Console.WriteLine(cnt);
	}
}


using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
	public static void Main()
	{
		var nk = Console.ReadLine().Split().Select(ulong.Parse).ToArray();
		var n = nk[0];
		var k = nk[1];

		var Z = new Dictionary<ulong, ulong>[10];
		for (var p = 0; p < Z.Length; p++)
			Z[p] = new Dictionary<ulong, ulong>();

		var A = new ulong[n];
		var lens = new int[n];

		var i = 0;
		foreach (var astr in Console.ReadLine().Split())
		{
			var a = ulong.Parse(astr);
			A[i] = a;
			lens[i] = astr.Length;
			var dict = Z[astr.Length];
			if (!dict.ContainsKey(a % k))
				dict[a % k] = 0;
			dict[a % k]++;
			i++;
		}

		var cnt = (ulong)0;
		for (var j = 0ul; j < n; j++)
		{
			for (var p = 1; p < Z.Length; p++)
			{
				var rem = (k - (A[j] * (ulong)Math.Pow(10, p)) % k) % k;
				ulong cp = 0;
				if (!Z[p].TryGetValue(rem, out cp)) cp = 0;

				if (lens[j] == p && rem == A[j] % k)
					cp--;

				cnt += cp;
			}
		}

		Console.WriteLine(cnt);
	}
}


using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
	public static void Main()
	{
		var nk = Console.ReadLine().Split().Select(int.Parse).ToArray();
		var n = nk[0];
		var k = nk[1];

		var Z = new Dictionary<int, int>[10];
		for (var p = 0; p < Z.Length; p++)
			Z[p] = new Dictionary<int, int>();

		var A = new int[n];
		var lens = new int[n];

		var i = 0;
		foreach (var astr in Console.ReadLine().Split())
		{
			var a = int.Parse(astr);
			A[i] = a;
			lens[i] = astr.Length;
			var dict = Z[astr.Length];
			if (!dict.ContainsKey(a % k))
				dict[a % k] = 0;
			dict[a % k]++;
			i++;
		}

		var cnt = 0;
		for (var j = 0; j < n; j++)
		{
			for (var p = 1; p < Z.Length; p++)
			{
				var rem = (k - (A[j] * (int)Math.Pow(10, p)) % k) % k;
				int cp = 0;
				if (!Z[p].TryGetValue(rem, out cp)) cp = 0;

				if (lens[j] == p && rem == A[j] % k)
					cp--;

				cnt += cp;
			}
		}

		Console.WriteLine(cnt);
	}
}


using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
	public static void Main()
	{
		var nk = Console.ReadLine().Split().Select(long.Parse).ToArray();
		var n = nk[0];
		var k = nk[1];

		var Z = new Dictionary<long, long>[9];
		for (var p = 0; p < Z.Length; p++)
			Z[p] = new Dictionary<long, long>();

		var A = new long[n];
		var lens = new int[n];

		var i = 0;
		foreach (var astr in Console.ReadLine().Split())
		{
			var a = long.Parse(astr);
			A[i] = a;
			lens[i] = astr.Length;
			var dict = Z[astr.Length];
			if (!dict.ContainsKey(a % k))
				dict[a % k] = 0;
			dict[a % k]++;
			i++;
		}

		var cnt = (long)0;
		for (var j = 0; j < n; j++)
		{
			for (var p = 1; p < Z.Length; p++)
			{
				var rem = (k - (A[j] * (long)Math.Pow(10, p)) % k) % k;
				long cp = 0;
				if (!Z[p].TryGetValue(rem, out cp)) cp = 0;

				if (lens[j] == p && rem == A[j] % k)
					cp--;

				cnt += cp;
			}
		}

		Console.WriteLine(cnt);
	}
}


using System;
using System.Collections.Generic;
using System.Linq;

public class Program
{
	public static void Main()
	{
		var nk = Console.ReadLine().Split().Select(long.Parse).ToArray();
		var n = nk[0];
		var k = nk[1];

		var Z = new Dictionary<long, long>[10];
		for (var p = 0; p < Z.Length; p++)
			Z[p] = new Dictionary<long, long>();

		var A = new long[n];
		var lens = new int[n];

		var i = 0;
		foreach (var astr in Console.ReadLine().Split())
		{
			var a = long.Parse(astr);
			A[i] = a;
			lens[i] = astr.Length;
			var dict = Z[astr.Length];
			if (!dict.ContainsKey(a % k))
				dict[a % k] = 0;
			dict[a % k]++;
			i++;
		}

		var cnt = (long)0;
		for (var j = 0; j < n; j++)
		{
			for (var p = 1; p < Z.Length; p++)
			{
				var rem = (k - (A[j] * (long)Math.Pow(10, p)) % k) % k;
				long cp = 0;
				if (!Z[p].TryGetValue(rem, out cp)) cp = 0;

				if (lens[j] == p && rem == A[j] % k)
					cp--;

				cnt += cp;
			}
		}

		Console.WriteLine(cnt);
	}
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

// -----------------------------------------------
// Framework <https://github.com/vain0x/procon>
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        $(writeln!(stderr(), "{} = {:?}", stringify!($arg), $arg).unwrap());*
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn f(mut n: i64, P: i64) -> i64 {
    assert!(n > 0);

    let mut l = 1;
    while n > 0 {
        l = (l * 10) % P;
        n /= 10;
    }

    l
}

fn pow(mut x: i64, mut n: i64, P: i64) -> i64 {
    let mut y = 1;
    while n > 0 {
        if n % 2 == 0 {
            x = (x * x) % P;
            n /= 2;
        } else {
            y = (y * x) % P;
            n -= 1;
        }
    }
    y % P
}

fn main() {
    // debug!(pow(3, 0, 2));

    let (N, P) = read!(usize, i64);
    let A = read![[i64]];

    let mut map: BTreeMap<i64, i64> = BTreeMap::new();
    for &a in &A {
        *map.entry(a % P).or_insert(0) += 1;
    }

    // debug!(map);

    let mut count = 0_i64;
    for &a in &A {
        let t = f(a, P);
        if t == 0 {
            if a % P == 0 {
                count += (N - 1) as i64;
            }
            continue;
        }

        let r = (P - (a % P) * pow(t, P - 2, P) % P) % P;

        let k = map.get(&r).cloned().unwrap_or(0);
        // debug!((a, r, k));

        count += k;

        if r == a % P {
            // debug!((a * f(a, P) + a));
            count -= 1;
        }
    }

    println!("{}", count)
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

// -----------------------------------------------
// Framework <https://github.com/vain0x/procon>
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        $(writeln!(stderr(), "{} = {:?}", stringify!($arg), $arg).unwrap());*
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn f(mut n: i64, P: i64) -> i64 {
    assert!(n > 0);

    let mut l = 1;
    while n > 0 {
        l = (l * 10) % P;
        n /= 10;
    }

    l
}

fn pow(mut x: i64, mut n: i64, P: i64) -> i64 {
    let mut y = 1;
    while n > 0 {
        if n % 2 == 0 {
            x = (x * x) % P;
            n /= 2;
        } else {
            y = (y * x) % P;
            n -= 1;
        }
    }
    y % P
}

fn main() {
    // debug!(pow(3, 0, 2));

    let (N, P) = read!(usize, i64);
    let A = read![[i64]];

    let mut map: BTreeMap<i64, i64> = BTreeMap::new();
    for &a in &A {
        *map.entry(a % P).or_insert(0) += 1;
    }

    // debug!(map);

    let mut count = 0_i64;
    for &a in &A {
        let t = f(a, P);
        if t == 0 {
            if a % P == 0 {
                count += (N - 1) as i64;
            }
            continue;
        }

        let r = (P - a * pow(t, P - 2, P) % P) % P;

        let k = map.get(&r).cloned().unwrap_or(0);
        // debug!((a, r, k));

        count += k;

        if r == a % P {
            // debug!((a * f(a, P) + a));
            count -= 1;
        }
    }

    println!("{}", count)
}


#![allow(unused_imports)]
#![allow(non_snake_case)]

use std::cell::RefCell;
use std::cmp::{max, min, Ordering};
use std::collections::*;
use std::fmt::{Debug, Formatter, Write as FmtWrite};
use std::io::{stderr, stdin, BufRead, Write};
use std::mem::{replace, swap};
use std::ops::*;
use std::rc::Rc;

// -----------------------------------------------
// Framework <https://github.com/vain0x/procon>
// -----------------------------------------------

#[allow(unused_macros)]
macro_rules! read {
    ([$t:ty] ; $n:expr) =>
        ((0..$n).map(|_| read!([$t])).collect::<Vec<_>>());
    ($($t:ty),+ ; $n:expr) =>
        ((0..$n).map(|_| read!($($t),+)).collect::<Vec<_>>());
    ([$t:ty]) =>
        (rl().split_whitespace().map(|w| w.parse().unwrap()).collect::<Vec<$t>>());
    ($t:ty) =>
        (rl().parse::<$t>().unwrap());
    ($($t:ty),*) => {{
        let buf = rl();
        let mut w = buf.split_whitespace();
        ($(w.next().unwrap().parse::<$t>().unwrap()),*)
    }};
}

#[allow(unused_macros)]
macro_rules! debug {
    ($($arg:expr),*) => {
        #[cfg(debug_assertions)]
        $(writeln!(stderr(), "{} = {:?}", stringify!($arg), $arg).unwrap());*
    };
}

#[allow(dead_code)]
fn rl() -> String {
    let mut buf = String::new();
    stdin().read_line(&mut buf).unwrap();
    buf.trim_right().to_owned()
}

trait IteratorExt: Iterator + Sized {
    fn vec(self) -> Vec<Self::Item> {
        self.collect()
    }
}

impl<T: Iterator> IteratorExt for T {}

// -----------------------------------------------
// Solution
// -----------------------------------------------

fn f(mut n: i64, P: i64) -> i64 {
    assert!(n > 0);

    let mut t = 1;
    while n > 0 {
        t = (t * 10) % P;
        n /= 10;
    }

    t
}

fn len(mut n: i64) -> i64 {
    assert!(n > 0);

    let mut l = 0;
    while n > 0 {
        l += 1;
        n /= 10;
    }

    l
}

fn pow(mut x: i64, mut n: i64, P: i64) -> i64 {
    let mut y = 1;
    while n > 0 {
        if n % 2 == 0 {
            x = (x * x) % P;
            n /= 2;
        } else {
            y = (y * x) % P;
            n -= 1;
        }
    }
    y
}

fn main() {
    // debug!(pow(0, 2, 2));

    let (_, P) = read!(usize, i64);
    let A = read![[i64]];
    let _N = A.len();

    let L = 13;

    // map[(l, r)] = #{ (m, n) | m != n, len(m) = l, n l = r }
    let mut map: BTreeMap<(i64, i64), i64> = BTreeMap::new();
    for &n in &A {
        for l in 1..L {
            let r = ((n % P) * pow(10 % P, l, P)) % P;
            *map.entry((l, r)).or_insert(0) += 1;
        }
    }

    debug!(map);

    let mut count = 0_i64;
    for &m in &A {
        let l = len(m);
        let r = (P - m % P) % P;
        let k = map.get(&(l, r)).cloned().unwrap_or(0);
        count += k;

        if ((m % P) * f(m, P) % P + m % P) % P == 0 {
            count -= 1;
        }

        debug!((m, l, r, k));
    }

    println!("{}", count)
}


use std::io;
use std::cmp::Ordering;

#[derive(Copy, Clone, Debug)]
struct Num {
    value: u64,
    len: i32,
    rem: u64,
}

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let rin = buf.split_whitespace().map(|c| c.parse::<u64>().unwrap()).collect::<Vec<_>>();
    let n = rin[0];
    let k = rin[1];

    let mut nums = std::iter::repeat(Num { value: 0, len: 0, rem: 0 }).take(n as usize).collect::<Vec<_>>();
    let mut len_to_rem = std::iter::repeat(Vec::<&Num>::new()).take(11).collect::<Vec<_>>();
    buf.clear();
    io::stdin().read_line(&mut buf).unwrap();
    for (i, v) in buf.split_whitespace().enumerate() {
        let value = v.parse::<u64>().unwrap();
        let len = v.len();
        let rem = value % k;
        nums[i] = Num { value, len: len as i32, rem };
    }
    nums.iter().take(n as usize).for_each(|c| {
        len_to_rem[c.len as usize].push(c);
    });
    len_to_rem.iter_mut().for_each(|c| c.sort_by(|&a, &b| a.rem.cmp(&b.rem)));

    let e10rem = (1..=9).fold(vec![1u64], |mut c, _| {
        let n = c.last().unwrap() * 10 % k;
        c.push(n);
        c
    });
    let len_has_rem = len_to_rem.iter().enumerate().filter_map(|c| if c.1.len() != 0 { Some(c.0) } else { None }).collect::<Vec<_>>();

    let mut ans = 0;
    for num in nums.iter().take(n as usize) {
        for &len in len_has_rem.iter() {
            let rem = (num.value * e10rem[len]) % k;
            let rem = if rem == 0 { 0 } else { k - rem };
            let l = lower_bound(&len_to_rem[len], rem, |c| c.rem);
            let r = upper_bound(&len_to_rem[len], rem, |c| c.rem);
            if l.is_some() && r.is_some() {
                let l = l.unwrap();
                let r = r.unwrap();
                let mut count = r - l + 1;
                if num.len as usize == len && num.rem == rem {
                    count -= 1;
                }
                ans += count;
            }
        }
    }
    println!("{}", ans);
}

fn upper_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => upper_bound(&slice[..m], v, f),
        Ordering::Less => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1).or(Some(m)),
    };
}

fn lower_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => lower_bound(&slice[..m], v, f),
        Ordering::Less => lower_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => lower_bound(&slice[..m], v, f).or(Some(m)),
    };
}


use std::io;
use std::cmp::Ordering;

#[derive(Copy, Clone, Debug)]
struct Num {
    value: u32,
    len: i32,
    rem: u32,
}

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let rin = buf.split_whitespace().map(|c| c.parse::<u32>().unwrap()).collect::<Vec<_>>();
    let n = rin[0];
    let k = rin[1];

    let mut nums = std::iter::repeat(Num { value: 0, len: 0, rem: 0 }).take(n as usize).collect::<Vec<_>>();
    let mut len_to_rem = std::iter::repeat(Vec::<&Num>::new()).take(11).collect::<Vec<_>>();
    buf.clear();
    io::stdin().read_line(&mut buf).unwrap();
    for (i, v) in buf.split_whitespace().enumerate() {
        let value = v.parse::<u32>().unwrap();
        let len = v.len();
        let rem = value % k;
        nums[i] = Num { value, len: len as i32, rem };
    }
    nums.iter().take(n as usize).for_each(|c| {
        len_to_rem[c.len as usize].push(c);
    });
    len_to_rem.iter_mut().for_each(|c| c.sort_by(|&a, &b| a.rem.cmp(&b.rem)));
    let e10rem = (1..9).fold(vec![1u32], |mut c, _| {
        let n = c.last().unwrap() * 10;
        c.push(n);
        c
    });
    let len_has_rem = len_to_rem.iter().enumerate().filter_map(|c| if c.1.len() != 0 { Some(c.0) } else { None }).collect::<Vec<_>>();

    let mut ans = 0;
    for num in nums.iter().take(n as usize) {
        for &len in len_has_rem.iter() {
            let rem = (num.value * e10rem[len]) % k;
            let rem = if rem == 0 { 0 } else { k - rem };
            let l = lower_bound(&len_to_rem[len], rem, |c| c.rem);
            let r = upper_bound(&len_to_rem[len], rem, |c| c.rem);
            if l.is_some() && r.is_some() {
                let l = l.unwrap();
                let r = r.unwrap();
                let mut count = r - l + 1;
                if num.len as usize == len && num.rem == rem {
                    count -= 1;
                }
                ans += count;
            }
        }
    }
    println!("{}", ans);
}

fn upper_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => upper_bound(&slice[..m], v, f),
        Ordering::Less => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1).or(Some(m)),
    };
}

fn lower_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => lower_bound(&slice[..m], v, f),
        Ordering::Less => lower_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => lower_bound(&slice[..m], v, f).or(Some(m)),
    };
}


use std::io;
use std::cmp::Ordering;

#[derive(Copy, Clone)]
struct Num {
    value: u64,
    len: i32,
    rem: u64,
}

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let rin = buf.split_whitespace().map(|c| c.parse::<u64>().unwrap()).collect::<Vec<_>>();
    let n = rin[0];
    let k = rin[1];

    let mut nums = std::iter::repeat(Num { value: 0, len: 0, rem: 0 }).take(n as usize).collect::<Vec<_>>();
    let mut len_to_rem = std::iter::repeat(Vec::<&Num>::new()).take(11).collect::<Vec<_>>();
    buf.clear();
    io::stdin().read_line(&mut buf).unwrap();
    for (i, v) in buf.split_whitespace().enumerate() {
        let value = v.parse::<u64>().unwrap();
        let len = v.len();
        let rem = value % k;
        nums[i] = Num { value, len: len as i32, rem };
    }
    nums.iter().take(n as usize).for_each(|c| {
        len_to_rem[c.len as usize].push(c);
    });
    len_to_rem.iter_mut().for_each(|c| c.sort_by(|&a, &b| a.rem.cmp(&b.rem)));

    let e10rem = (1..=10).fold(vec![1u64], |mut c, _| {
        let n = c.last().unwrap() * 10 % k;
        c.push(n);
        c
    });
    let len_has_rem = len_to_rem.iter().enumerate().filter_map(|c| if c.1.len() != 0 { Some(c.0) } else { None }).collect::<Vec<_>>();

    let mut ans = 0u64;
    for num in nums.iter().take(n as usize) {
        for &len in len_has_rem.iter() {
            let rem = (num.value * e10rem[len]) % k;
            let rem = if rem == 0 { 0 } else { k - rem };
            let l = lower_bound(&len_to_rem[len], rem, |c| c.rem);
            let r = upper_bound(&len_to_rem[len], rem, |c| c.rem);
            if l.is_some() && r.is_some() {
                let l = l.unwrap();
                let r = r.unwrap();
                if num.len as usize == len && num.rem == rem {
                    ans += (r - l) as u64;
                } else {
                    ans += (r - l + 1) as u64
                }
            }
        }
    }
    println!("{}", ans);
}

fn upper_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => upper_bound(&slice[..m], v, f),
        Ordering::Less => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1).or(Some(m)),
    };
}

fn lower_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => lower_bound(&slice[..m], v, f),
        Ordering::Less => lower_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => lower_bound(&slice[..m], v, f).or(Some(m)),
    };
}


use std::io;
use std::cmp::Ordering;

#[derive(Copy, Clone)]
struct Num {
    value: u64,
    len: i32,
    rem: u64,
}

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let rin = buf.split_whitespace().map(|c| c.parse::<u64>().unwrap()).collect::<Vec<_>>();
    let n = rin[0];
    let k = rin[1];

    let mut nums = std::iter::repeat(Num { value: 0, len: 0, rem: 0 }).take(n as usize).collect::<Vec<_>>();
    let mut len_to_rem = std::iter::repeat(Vec::<&Num>::new()).take(11).collect::<Vec<_>>();
    buf.clear();
    io::stdin().read_line(&mut buf).unwrap();
    for (i, v) in buf.split_whitespace().enumerate() {
        let value = v.parse::<u64>().unwrap();
        let len = v.len();
        let rem = value % k;
        nums[i] = Num { value, len: len as i32, rem };
    }
    nums.iter().take(n as usize).for_each(|c| {
        len_to_rem[c.len as usize].push(c);
    });
    len_to_rem.iter_mut().for_each(|c| c.sort_by(|&a, &b| a.rem.cmp(&b.rem)));

    let e10rem = (1..=9).fold(vec![1u64], |mut c, _| {
        let n = c.last().unwrap() * 10 % k;
        c.push(n);
        c
    });
    let len_has_rem = len_to_rem.iter().enumerate().filter_map(|c| if c.1.len() != 0 { Some(c.0) } else { None }).collect::<Vec<_>>();

    let mut ans = 0u64;
    for num in nums.iter().take(n as usize) {
        for &len in len_has_rem.iter() {
            let rem = (num.value * e10rem[len]) % k;
            let rem = if rem == 0 { 0 } else { k - rem };
            let l = lower_bound(&len_to_rem[len], rem, |c| c.rem);
            let r = upper_bound(&len_to_rem[len], rem, |c| c.rem);
            if l.is_some() && r.is_some() {
                let l = l.unwrap();
                let r = r.unwrap();
                if num.len as usize == len && num.rem == rem {
                    ans += (r - l) as u64;
                } else {
                    ans += (r - l + 1) as u64
                }
            }
        }
    }
    println!("{}", ans);
}

fn upper_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => upper_bound(&slice[..m], v, f),
        Ordering::Less => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1).or(Some(m)),
    };
}

fn lower_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => lower_bound(&slice[..m], v, f),
        Ordering::Less => lower_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => lower_bound(&slice[..m], v, f).or(Some(m)),
    };
}


use std::io;
use std::cmp::Ordering;

#[derive(Copy, Clone, Debug)]
struct Num {
    value: u32,
    len: i32,
    rem: u32,
}

fn main() {
    let mut buf = String::new();
    io::stdin().read_line(&mut buf).unwrap();
    let rin = buf.split_whitespace().map(|c| c.trim().parse::<u32>().unwrap()).collect::<Vec<_>>();
    let n = rin[0];
    let k = rin[1];

    let mut nums = [Num { value: 0, len: 0, rem: 0 }; 200000];
    let mut len_to_rem = std::iter::repeat(Vec::<&Num>::new()).take(11).collect::<Vec<_>>();
    buf.clear();
    io::stdin().read_line(&mut buf).unwrap();
    for (i, v) in buf.split_whitespace().enumerate() {
        let value = v.trim().parse::<u32>().unwrap();
        let len = v.len();
        let rem = value % k;
        nums[i] = Num { value, len: len as i32, rem };
    }
    nums.iter().take(n as usize).for_each(|c| {
        len_to_rem[c.len as usize].push(c);
    });
    len_to_rem.iter_mut().for_each(|c| c.sort_by(|&a, &b| a.rem.cmp(&b.rem)));
    let e10rem = (1..9).fold(vec![1u32], |mut c, _| {
        let n = c.last().unwrap() * 10;
        c.push(n);
        c
    });
    let len_has_rem = len_to_rem.iter().enumerate().filter_map(|c| if c.1.len() != 0 { Some(c.0) } else { None }).collect::<Vec<_>>();

    let mut ans = 0;
    for num in nums.iter().take(n as usize) {
        for &len in len_has_rem.iter() {
            let rem = (num.value * e10rem[len]) % k;
            let rem = if rem == 0 { 0 } else { k - rem };
            let l = lower_bound(&len_to_rem[len], rem, |c| c.rem);
            let r = upper_bound(&len_to_rem[len], rem, |c| c.rem);
            if l.is_some() && r.is_some() {
                let l = l.unwrap();
                let r = r.unwrap();
                let mut count = r - l + 1;
                if num.len as usize == len && num.rem == rem {
                    count -= 1;
                }
                ans += count;
            }
        }
    }
    println!("{}", ans);
}

fn upper_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => upper_bound(&slice[..m], v, f),
        Ordering::Less => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => upper_bound(&slice[m + 1..], v, f).map(|c| m + c + 1).or(Some(m)),
    };
}

fn lower_bound<Item, F, K>(slice: &[Item], v: K, f: F) -> Option<usize> where F: Fn(&Item) -> K, K: std::cmp::Ord {
    let len = slice.len();
    if len == 0 {
        return None;
    }
    if len == 1 {
        return match f(&slice[0]).cmp(&v) {
            Ordering::Equal => Some(0),
            _ => None,
        };
    }
    let l = 0usize;
    let r = len - 1;
    let m = (l + r) / 2;
    return match f(&slice[m]).cmp(&v) {
        Ordering::Greater => lower_bound(&slice[..m], v, f),
        Ordering::Less => lower_bound(&slice[m + 1..], v, f).map(|c| m + c + 1),
        Ordering::Equal => lower_bound(&slice[..m], v, f).or(Some(m)),
    };
}


macro_rules! parse_line {
    ($t: ty) => ({
        let mut a_str = String::new();
        std::io::stdin().read_line(&mut a_str).expect("read error");
        let a_str = a_str.trim();
        a_str.parse::<$t>().expect("parse error")
    });
    ($($t: ty),+) => ({
        let mut a_str = String::new();
        std::io::stdin().read_line(&mut a_str).expect("read error");
        let mut a_iter = a_str.split_whitespace();
        (
            $(
            a_iter.next().unwrap().parse::<$t>().expect("parse error"),
            )+
        )
    })
}

macro_rules! parse_line_to_vec {
    ($t: ty) => {{
        let mut a_str = String::new();
        std::io::stdin().read_line(&mut a_str).expect("read error");
        (a_str
            .split_whitespace()
            .map(|x| x.parse::<$t>().unwrap())
            .collect::<Vec<$t>>())
    }};
}

fn digits(mut x: u64) -> u64 {
    let mut result = 0;
    while x > 0 {
        x /= 10;
        result += 1;
    }
    return result;
}

fn solve() {
    let (_n, k) = parse_line!(usize, u64);
    let a = parse_line_to_vec!(u64);
    let mut counts = std::collections::HashMap::<(u64, u64), u64>::new();
    for &x in a.iter() {
        let key = (x % k, digits(x));
        *counts.entry(key).or_insert(0) += 1;
    }
    let mut result = 0;
    for base in a {
        let mut x = base;
        for j in 1..11u64 {
            x = x * 10 % k;
            result += match counts.get(&((k - x) % k, j)) {
                None => 0,
                Some(&val) => val - if (k - x) % k == base % k && digits(base) == j {1} else {0},
            };
        }
    }
    println!("{}", result);
}

fn main() {
    let tests = 1; // parse_line!(usize);
    for _ in 0..tests {
        solve();
    }
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

const (
	MaxN = 200005
	MaxDigits = 11
)

var n, k uint64
var a [MaxN]uint64
var counts [MaxDigits]map[uint64]uint64

func digitCount(n uint64) int {
	cnt := 0
	for n > 0 {
		cnt++
		n /= 10
	}
	return cnt
}

func main() {
	buf := bufio.NewReader(os.Stdin)
	for i := 0; i < MaxDigits; i++ {
		counts[i] = make(map[uint64]uint64)
	}
	fmt.Fscanf(buf, "%d %d\n", &n, &k)
	for i := uint64(0); i < n; i++ {
		fmt.Fscanf(buf, "%d ", &a[i])
		tmp := uint64(a[i])
		for j := uint64(1); j < MaxDigits; j++ {
			tmp = tmp * 10
			counts[j][tmp % k]++
		}
	}

	ans := uint64(0)
	for i := uint64(0); i < n; i++ {
		digits := digitCount(a[i])
		ans += counts[digits][(k - a[i] % k) % k]
		if (a[i] * uint64(math.Pow10(digits)) + a[i]) % k == 0 {
			ans--
		}
	}

	fmt.Println(ans)
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

const (
	MaxN = 200005
	MaxDigits = 10
)

var n, k int64
var a [MaxN]int64
var counts [MaxDigits]map[int64]int64

func digitCount(n int64) int {
	cnt := 0
	for n > 0 {
		cnt++
		n /= 10
	}
	return cnt
}

func main() {
	buf := bufio.NewReader(os.Stdin)
	for i := 0; i < MaxDigits; i++ {
		counts[i] = make(map[int64]int64)
	}
	fmt.Fscanf(buf, "%d %d\n", &n, &k)
	for i := int64(0); i < n; i++ {
		fmt.Fscanf(buf, "%d ", &a[i])
		tmp := int64(a[i])
		for j := int64(1); j < MaxDigits; j++ {
			tmp = tmp * 10
			counts[j][tmp % k]++
		}
	}

	ans := int64(0)
	for i := int64(0); i < n; i++ {
		digits := digitCount(a[i])
		ans += counts[digits][(k - a[i] % k) % k]
		if (a[i] * int64(math.Pow10(digits)) + a[i]) % k == 0 {
			ans--
		}
	}

	fmt.Println(ans)
}


package main

import (
	"bufio"
	"fmt"
	"math"
	"os"
)

const (
	MaxN = 200005
	MaxDigits = 10
)

var n, k int64
var a [MaxN]int64
var counts [MaxDigits]map[int64]int

func digitCount(n int64) int {
	cnt := 0
	for n > 0 {
		cnt++
		n /= 10
	}
	return cnt
}

func main() {
	buf := bufio.NewReader(os.Stdin)
	for i := 0; i < MaxDigits; i++ {
		counts[i] = make(map[int64]int)
	}
	fmt.Fscanf(buf, "%d %d\n", &n, &k)
	for i := int64(0); i < n; i++ {
		fmt.Fscanf(buf, "%d ", &a[i])
		tmp := int64(a[i])
		for j := int64(1); j < MaxDigits; j++ {
			tmp = tmp * 10
			counts[j][tmp % k]++
		}
	}

	ans := 0
	for i := int64(0); i < n; i++ {
		digits := digitCount(a[i])
		ans += counts[digits][(k - a[i] % k) % k]
		if (a[i] * int64(math.Pow10(digits)) + a[i]) % k == 0 {
			ans--
		}
	}

	fmt.Println(ans)
}


from sys import stdin, stdout
ti = lambda : stdin.readline().strip()
os = lambda i : stdout.write(str(i) + '\n')
ma = lambda fxn, ti : map(fxn, ti.split())
ol = lambda arr : stdout.write(' '.join(element for element in arr) + '\n')
olws = lambda arr : stdout.write(''.join(element for element in arr) + '\n')

class Digit:
	def __init__(self):
		self.count = {}

	def increment(self, k):
		if self.count.has_key(k):
			got = self.count[k]
			self.count[k] += 1
		else:
			self.count[k] = 1

	def found(self, k):
		if self.count.has_key(k):
			return self.count[k]
		else:
			return 0

n, mod = ma(int, ti())
array = ma(int, ti())

ans = 0
digits = [None]*11
for i in range(11):
	digits[i] = Digit()

for i in range(n):
	temp = array[i]%mod

	for j in range(10):
		temp *= 10
		temp %= mod

		digits[j+1].increment(temp)

for i in range(n):
	temp = array[i]
	count = 0
	while temp>0:
		temp /= 10
		count += 1

	find = mod-array[i]%mod
	find %= mod
	ans += digits[count].found(find)

for i in range(n):
	temp1 = array[i]%mod
	temp2 = array[i]

	while temp2 > 0:
		temp2 /= 10
		temp1 *= 10
		temp1 %= mod

	if ((temp1 + array[i])%mod == 0):
		ans -= 1

os(ans)


cnt = [dict() for _ in range(11)]

n, k = map(int, raw_input().split())
a = map(int, raw_input().split())

for it in a:
  ln = len(str(it))
  curr = it % k
  cnt[ln][curr] = cnt[ln].get(curr, 0) + 1

rs = 0
for it in a:
  for i in range(1, 11):
    curr = it * (10 ** i) % k
    rs += cnt[i].get((k - curr) % k, 0)
    if len(str(it)) == i and it % k == (k - curr) % k:
      rs -= 1

print rs