专栏文章
题解:P8712 [蓝桥杯 2020 省 B1] 整数拼接
P8712题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miqitlps
- 此快照首次捕获于
- 2025/12/04 05:30 3 个月前
- 此快照最后确认于
- 2025/12/04 05:30 3 个月前
1.题目描述
给定一个长度为 的数组 。你可以从中选出两个数 和 (),然后将 和 一前一后拼成一个新的整数。例如12和345可以拼成12345或34512。注意交换 和 的顺序总是被视为 种拼法,即便是 时。请你计算有多少种拼法满足拼出的整数是 的倍数。
2.思路
由于 ,使用时间复杂度为 的算法枚举每种拼接显然不可行。面对这个问题,我们需要一种储存数组 中信息的方法,可以让我们在每次遍历 时以较少的时间复杂度得知能与 拼接的整数个数。
设数组中两个元素 和 的数字位数分别为 和 ,因为拼接后的数是 的倍数,所以有 ,即 。由于 ,即 最多有十位,我们可以开 个哈希表,对于第 个哈希表,存储 的每个值出现的次数。这样我们在遍历时就能用哈希表里的值进行快速相加了。
3.注意事项
-
由于 ,我们把两个模 的余数相乘时会超出
int的范围。此外拼接方法的总数在极限情况下也会超出int的范围。所以记得开long long。 -
按以上方法计算会多算到自己与自己拼接的情况。所以当 时,要把答案减 。
-
可以用
log10(x) + 1快速计算 的数字位数。
4.代码
CPP#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
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...