Codeforces 1029D(数论+思维)

传送门

题面:

D. Concatenated Multiples

time limit per test

2 seconds

memory limit per test

256 megabytes

input

standard input

output

standard output

You are given an array aa, consisting of nn positive integers.

Let's call a concatenation of numbers xx and yy the number that is obtained by writing down numbers xx and yy one right after another without changing the order. For example, a concatenation of numbers 1212 and 34563456 is a number 123456123456.

Count the number of ordered pairs of positions (i,j)(i,j) (i≠ji≠j) in array aa such that the concatenation of aiai and ajaj is divisible by kk.

Input

The first line contains two integers nn and kk (1≤n≤2⋅1051≤n≤2⋅105, 2≤k≤1092≤k≤109).

The second line contains nn integers a1,a2,…,ana1,a2,…,an (1≤ai≤1091≤ai≤109).

Output

Print a single integer — the number of ordered pairs of positions (i,j)(i,j) (i≠ji≠j) in array aa such that the concatenation of aiai and ajaj is divisible by kk.

Examples

input

Copy

6 11
45 1 10 12 11 7

output

Copy

7

input

Copy

4 2
2 78 4 10

output

Copy

12

input

Copy

5 2
3 7 19 3 3

output

Copy

0

Note

In the first example pairs (1,2)(1,2), (1,3)(1,3), (2,3)(2,3), (3,1)(3,1), (3,4)(3,4), (4,2)(4,2), (4,3)(4,3) suffice. They produce numbers 451451, 45104510, 110110, 10451045, 10121012, 121121, 12101210, respectively, each of them is divisible by 1111.

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

In the third example no pair is sufficient.

题意:

    给你n个数,每个数可以两两拼接成一个新的数。问通过这样拼接而构成的数中能够成为被k乘除的个数。

题目分析:

    这道题的做法相当的巧妙!(完美融入了数论的知识)(膜出题人的大脑洞)。

    首先,直接暴力做铁定超时,因此我们需要做一些算法优化。

    首先,对于两个数x,y。倘若让他们拼接成一个新的数S,我们设y的长度为len,则有:

    而因为要判断S是否整除k,则将S%k,则有:(x*pow(10,len)%k+y%k)%k=0

    而根据取模的性质,我们可以继续得到:

    ( x*pow( 10,len )%k+y%k )%k=k%k 

    x*pow(10,len)%k=( k-y%k )%k

    而在这个式子中,对于左式,我们可以把每一个左式都预处理出来,存进桶里。

    之后我们只需要枚举一遍a[i],计算 ( k - y%k )%k 。如果两个结果相等,那么就加在res。

    最后我们还需要减去a[i]和a[i]自己配对的情况即为答案。

代码:

#include <bits/stdc++.h>
#define maxn 200005
using namespace std;
typedef long long ll;
int a[maxn];
map<int,ll>mp[20];
int main()
{
    int n,k;
    cin>>n>>k;
    for(int i=1;i<=n;i++){//预处理出来每一个(x*pow(10,len)%k)
        scanf("%I64d",&a[i]);
        ll x=a[i];
        for(int j=1;j<=10;j++){
            x=x*10%k;
            mp[j][x]++;
        }
    }
    ll res=0;
    for(int i=1;i<=n;i++){
        int len=log10(a[i])+1;//获取10进制的位数
        res+=mp[len][(k-a[i]%k)%k];//获取答案
        ll x=1;
        for(int i=1;i<=len;i++){
            x=x*10%k;
        }
        if((a[i]*x%k+a[i]%k)%k==0) res--;//排除自己跟自己配对的情况
    }
    cout<<res<<endl;
}
原文地址:https://www.cnblogs.com/Chen-Jr/p/11007211.html