题解:P8712 [蓝桥杯 2020 省 B1] 整数拼接
1.题目描述
给定一个长度为
n 的数组A_1,A_2,\cdots,A_n 。你可以从中选出两个数A_i 和A_j (i\neq j ),然后将A_i 和A_j 一前一后拼成一个新的整数。例如12和345可以拼成12345或34512。注意交换A_i 和A_j 的顺序总是被视为2 种拼法,即便是A_i=A_j 时。请你计算有多少种拼法满足拼出的整数是
K 的倍数。
2.思路
由于
设数组中两个元素
3.注意事项
-
由于
K \le 10^5 ,我们把两个模K 的余数相乘时会超出int的范围。此外拼接方法的总数在极限情况下也会超出int的范围。所以记得开long long。 -
按以上方法计算会多算到自己与自己拼接的情况。所以当
A_i \cdot 10^u + A_i \equiv 0 \pmod K 时,要把答案减1 。 -
可以用
log10(x) + 1快速计算x 的数字位数。
4.代码
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5+5;
int n, k, a[N];
long long pw[11]; // 10^u % k
unordered_map<int, int> mp[11];
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
cin >> n >> k;
pw[0] = 1;
for (int i = 1; i <= 10; i++)
pw[i] = (pw[i-1] * 10) % k;
for (int i = 1; i <= n; i++) {
cin >> a[i];
for (int j = 1; j <= 10; j++)
mp[j][a[i] * pw[j] % k]++;
}
long long ans = 0;
for (int i = 1; i <= n; i++) {
int len = log10(a[i]) + 1, mod = (k - a[i] % k) % k; // mod等价于数学上的-a[i] mod k
ans += mp[len][mod];
if (a[i] * pw[len] % k == mod)
ans--;
}
cout << ans << endl;
return 0;
}
5.复杂度分析
时间复杂度:
The End