整数拼接
整数拼接
给定一个长度为 的数组 。
你可以从中选出两个数 和 ( 不等于 ),然后将 和 一前一后拼成一个新的整数。
例如 和 可以拼成 或 。
注意交换 和 的顺序总是被视为 种拼法,即便是 时。
请你计算有多少种拼法满足拼出的整数是 的倍数。
输入格式
第一行包含 个整数 和 。
第二行包含 个整数 。
输出格式
一个整数代表答案。
,
,
输入样例:
4 2 1 2 3 4
输出样例:
6
解题思路
很容易想到两个数两个数去枚举,但这样的时间复杂度是的,因此需要进行优化。
我们任意选择两个数,,对其进行拼接,得到,其中,即数字的位数。我们要找的是有多个这样形式的数,满足。
我们可以通过枚举每一个数,把这个数当作上式的,这时和都是一个确定的值,只需查看有多少个,满足,进行一下变化,即有多少个满足。
我们可以进行预处理,用哈希表来统计每一个数乘上后模得到的余数的次数。这里,每一个数都要取。原理是开个哈希表,然后用第个哈希表来统计每个数乘上后模得到的余数的次数。
预处理完后,当再枚举每一个数时,我们就可以直接查第个哈希表,查看有多少个数乘上的次方后,后是的(当然,这里要转换为非负的余数)。
当然,如果这个数乘上的次方模等于,即,那么我们的结果要减去一个,因为在预处理的时候,我们是把这种情况也统计进去的。
AC代码如下:
1 #include <cstdio> 2 #include <string> 3 #include <algorithm> 4 using namespace std; 5 6 typedef long long LL; 7 8 const int N = 1e5 + 10; 9 10 int a[N], cnt[15][N]; 11 12 int main() { 13 int n, m; 14 scanf("%d %d", &n, &m); 15 for (int i = 0; i < n; i++) { 16 scanf("%d", a + i); 17 18 LL t = a[i] % m; 19 for (int i = 1; i <= 10; i++) { 20 t = t * 10 % m; 21 cnt[i][t]++; // 统计得到每个数的余数的次数 22 } 23 } 24 25 LL ret = 0; 26 for (int i = 0; i < n; i++) { 27 int len = to_string(a[i]).size(); 28 ret += cnt[len][(-a[i] % m + m) % m]; 29 30 LL t = a[i] % m; 31 while (len--) { 32 t = t * 10 % m; 33 } 34 if (t == (-a[i] % m + m) % m) ret--; // 除去这个数本身进行拼接的次数 35 } 36 37 printf("%lld", ret); 38 39 return 0; 40 }
参考资料
AcWing 2068. 整数拼接(蓝桥杯C++ AB组辅导课):https://www.acwing.com/video/2024/
本文来自博客园,作者:onlyblues,转载请注明原文链接:https://www.cnblogs.com/onlyblues/p/16039875.html
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探
· 为什么 退出登录 或 修改密码 无法使 token 失效