【题解】codeforces1029D[Codeforces Round #506 (Div. 3)]D.Concatenated Multiples 排序

32 篇文章 0 订阅
25 篇文章 0 订阅

Description

You are given an array a a a, consisting of n n n positive integers.

Let’s call a concatenation of numbers x x x and y y y the number that is obtained by writing down numbers x x x and y y y one right after another without changing the order. For example, a concatenation of numbers 12 12 12 and 3456 3456 3456 is a number 123456 123456 123456.

Count the number of ordered pairs of positions ( i , j ) ( i ≠ j ) (i,j) (i≠j) (i,j)(i̸=j) in array a such that the concatenation of a i a_i ai and a j a_j aj is divisible by k k k.

Input

The first line contains two integers n n n and k k k ( 1 ≤ n ≤ 2 × 1 0 5 , 2 ≤ k ≤ 1 0 9 ) (1≤n≤2\times10^5, 2≤k≤10^9) (1n2×105,2k109).

The second line contains n n n integers a 1 , a 2 , ⋯   , a n a_1,a_2,\cdots,a_n a1,a2,,an ( 1 ≤ a i ≤ 1 0 9 ) (1≤a_i≤10^9) (1ai109).

Output

Print a single integer — the number of ordered pairs of positions ( i , j ) ( i ≠ j ) (i,j) (i≠j) (i,j)(i̸=j) in array a such that the concatenation of a i a_i ai and a j a_j aj is divisible by k k k.

Examples

Input

6 11
45 1 10 12 11 7

Output

7

Input

4 2
2 78 4 10

Output

12

Input

5 2
3 7 19 3 3

Output

0

Note

In the first example pairs ( 1 , 2 ) , ( 1 , 3 ) , ( 2 , 3 ) , ( 3 , 1 ) , ( 3 , 4 ) , ( 4 , 2 ) , ( 4 , 3 ) (1,2), (1,3), (2,3), (3,1), (3,4), (4,2), (4,3) (1,2),(1,3),(2,3),(3,1),(3,4),(4,2),(4,3) suffice. They produce numbers 451 , 4510 , 110 , 1045 , 1012 , 121 , 1210 451, 4510, 110, 1045, 1012, 121, 1210 451,4510,110,1045,1012,121,1210, respectively, each of them is divisible by 11 11 11.

In the second example all n ( n − 1 ) n(n−1) n(n1) pairs suffice.

In the third example no pair is sufficient.


记录每一个位数出现的模数,排序后统计每一个位数出现的需要的模数的个数,注意不要重复计算。

#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=2e5+10;
int n,k,fac[11],len[N];
ll cnt,a[N];
vector<int>vx[11];
int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&k);fac[0]=1;
	for(int i=1;i<=10;i++)fac[i]=fac[i-1]*10%k;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&a[i]);
		len[i]=log10(a[i])+1;
		vx[len[i]].push_back(a[i]%k);
	}
	for(int i=0;i<=10;i++)sort(vx[i].begin(),vx[i].end());
	for(int i=1;i<=n;i++)
	{
		for(int j=1;j<=10;j++)
		{
			int mod=(a[i]*fac[j])%k;
			int key=(k-mod)%k;
			int l=lower_bound(vx[j].begin(),vx[j].end(),key)-vx[j].begin();
			int r=upper_bound(vx[j].begin(),vx[j].end(),key)-vx[j].begin();
			cnt+=r-l;
			if(len[i]==j&&(mod+a[i]%k)%k==0)cnt--;//去掉多算的 
		}
	}
	printf("%lld\n",cnt);
	return 0;
}

总结

这题看数据范围发现暴力不可解,可以在每一个位数下记录出现的 k k k 模数,再进行计算。可以通过位数和模数来判断是否把自己给算进去了。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值