传送门
题面:
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
#define maxn 200005
using namespace std;
typedef long long ll;
int a[maxn];
mapmp[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<