专栏文章

题解:P8712 [蓝桥杯 2020 省 B1] 整数拼接

P8712题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@miqitlps
此快照首次捕获于
2025/12/04 05:30
3 个月前
此快照最后确认于
2025/12/04 05:30
3 个月前
查看原文

1.题目描述

给定一个长度为 nn 的数组 A1,A2,,AnA_1,A_2,\cdots,A_n。你可以从中选出两个数 AiA_iAjA_jiji\neq j),然后将 AiA_iAjA_j 一前一后拼成一个新的整数。例如 12345 可以拼成 1234534512。注意交换 AiA_iAjA_j 的顺序总是被视为 22 种拼法,即便是 Ai=AjA_i=A_j 时。
请你计算有多少种拼法满足拼出的整数是 KK 的倍数。

2.思路

由于 1n1051 \le n \le 10^5,使用时间复杂度为 O(n2)\mathcal O(n^2) 的算法枚举每种拼接显然不可行。面对这个问题,我们需要一种储存数组 AA 中信息的方法,可以让我们在每次遍历 AiA_i 时以较少的时间复杂度得知能与 AiA_i 拼接的整数个数。
设数组中两个元素 AjA_jAiA_i 的数字位数分别为 vvuu,因为拼接后的数是 KK 的倍数,所以有 Aj10u+Ai0(modK)A_j \cdot 10^u + A_i \equiv 0 \pmod K,即 Aj10uAi(modK)A_j \cdot 10^u \equiv -A_i \pmod K。由于 Ai109A_i \le 10^9,即 AiA_i 最多有十位,我们可以开 1010 个哈希表,对于第 pp 个哈希表,存储 Ai10umodKA_i \cdot 10^u \mod K 的每个值出现的次数。这样我们在遍历时就能用哈希表里的值进行快速相加了。

3.注意事项

  • 由于 K105K \le 10^5,我们把两个模 KK 的余数相乘时会超出int的范围。此外拼接方法的总数在极限情况下也会超出int的范围。所以记得开long long
  • 按以上方法计算会多算到自己与自己拼接的情况。所以当 Ai10u+Ai0(modK)A_i \cdot 10^u + A_i \equiv 0 \pmod K 时,要把答案减 11
  • 可以用log10(x) + 1快速计算 xx 的数字位数。

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.复杂度分析

时间复杂度:O(nlog10maxAi)\mathcal O(n \log_{10} \max A_i)

The End

评论

0 条评论,欢迎与作者交流。

正在加载评论...