Concatenated Multiples CodeForces - 1029D

You are given an array a, consisting of n positive integers.
Let’s call a concatenation of numbers x and y the number that is obtained by writing down numbers x and y one right after another without changing the order. For example, a concatenation of numbers 12 and 3456 is a number 123456.
Count the number of ordered pairs of positions (i,j) (i≠j) in array a such that the concatenation of aiai and ajaj is divisible by k.

Input
The first line contains two integers nn and kk (1≤n≤2⋅10^5, 2≤k≤10^9).
The second line contains nn integers a1,a2,…,an (1≤ai≤10^9).

Output
Print a single integer — the number of ordered pairs of positions (i,j) (i≠j) in array a such that the concatenation of ai and aj is divisible by 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) suffice. They produce numbers 451, 4510, 110, 1045, 1012, 121, 1210, respectively, each of them is divisible by 11.
In the second example all n(n−1) pairs suffice.
In the third example no pair is sufficient.

首先暴力枚举O(n^2)肯定会挂,考虑到取模,可以列式推导试试
若x y 符合条件则
(x * 10^(log10(y) + 1) + y) % k = 0
即 x * 10^(log10(y) + 1) % k + y % k = n * k
化简 (x * 10(len) ) % k = (k - y) % k
预处理出(x * 10^len) % k,再循环一遍找y,对于y看是否有符合条件的x存在
注意x与x相连的情况要去掉,咋去掉呢,它本身是x,查看一下若这个数作为y也合理的话说明算重要减去1

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

int main()
{
    scanf("%d%d",&n,&k);
    for(int i = 1;i <= n; ++i)
    {
        scanf("%lld",&a[i]);
        long long x = a[i];
        for(int j = 1;j <= 11; ++j)
        {
            x = (x * 10) % 10;
            d[j][x]++;
        }
        long long ans = 0;
        for(int i = 1;i <= n; ++i)
        {
            int len = log10(a[i]) + 1;
            if(d[len][(k - a[i]) % k]) ans++:
            long long x = 1;
            for(int j = 1;j <= len; ++j) x = (x * 10) % k;
             if(((a[i] * x) % k + a[i] % k) % k == 0) ans--;
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值