题意
给你N个数字和一个K,问一共有几种拼接数字的方式使得到的数字是K的倍数,拼接:“234”和“123”拼接得到“234123”
分析:
- N <= 2e5,简单的暴力O(N^2)枚举肯定超时
- 数字A和B拼接,B的位数最多10位,如果我们知道位数为(1-10)的数字和A拼接满足是K的倍数这样的数字有几个,就可以在N*10的复杂度下完成所有的拼接
- 在读入数据的时候,我们可以统计出数字的位数和对K取余的结果,这样我们就可以在O(1)的时间内得到所有满足的情况
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include<bits/stdc++.h> #include <iostream> #include <cmath> #include <map> #include <vector> #include <set> #include <algorithm> #define ll long long #define ull unsigned long long #define N 200005 using namespace std; ll a[N]; // 获取长度 int getlen(int x) { int sum = 0; while (x) { ++sum; x /= 10; } return sum; } map<int, int> mp[11]; int main() { int n, k; while (scanf("%d%d", &n, &k) != EOF) { for (int i = 0; i < n; ++i) { scanf("%lld", &a[i]); int len = getlen(a[i]); mp[len][a[i] % k]++; } ll ans = 0; // 枚举N个数字 for (int i = 0; i < n; ++i) { ll mul = 1; int len = getlen(a[i]); mp[len][a[i] % k]--; // 对每个数字,分别对位数为 j 的数字进行拼接 for (int j = 1; j <= 10; ++j) { mul *= 10; ull temp = a[i] * mul; if (mp[j].find((k - temp % k) % k) != mp[j].end()) ans += mp[j][(k - temp % k) % k]; } mp[len][a[i] % k]++; } printf("%I64d ", ans); for (int i = 0; i < 11; ++i) mp[i].clear(); } return 0; }