原题链接:蓝桥杯2020年第十一届省赛真题-整数小拼接 - C语言网 (dotcpp.com)
题目描述
给定一个长度为 的数组 。你可以从中选出两个数 ,然后将 和 一前一后拼成一个新的整数。例如 12 和 345 可以拼成 12345 或 34512 。注意交换 和 的顺序被视为 2 种拼法,即便是 。
请你计算有多少种拼法满足拼出的整数小于等于 。
输入格式
第一行包含 2 个整数 和 。 第二行包含 个整数 。
输出格式
一个整数代表答案。
样例输入
4 33 1 2 3 4
样例输出
8
第一种解法:暴力枚举 30pts
使用两层循环迭代所有可能的组合,并判断连在一起是否小于 K 。
可以估计出算法的时间复杂度为 ,也就是只能通过30%的用例,得分 30 pts 。
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 100100;
int n;
long long k, a[MAX_N], ans;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
for (int i = 1; i <= n; ++i) {
for (int j = 1; j <= n; ++j) {
if (i == j) {
continue;
}
if (a[i] * (long long)pow(10, int(log10(a[j]) + 1)) + a[j] <= k) {
ans ++;
}
}
}
cout << ans << endl;
return 0;
}
第二种解法:二分法 100pts
即首先将原数组先排序,然后用一层循环枚举每一个 ,然后利用二分查找,找出能够满足条件的 ,估计时间复杂度为 。
拼接两个整数时,可以使用 来计算整数 的位数。
二分查找可以自己写一个,也可以选择直接用C++函数库里的 。
注意:不要忘记开 ,因为拼接后的数可以很大。
#include <bits/stdc++.h>
using namespace std;
const int MAX_N = 100100;
int n;
long long k, a[MAX_N], ans;
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
cout.tie(0);
cin >> n >> k;
for (int i = 1; i <= n; ++i) {
cin >> a[i];
}
sort(a + 1, a + n + 1);
for (int i = 1; i <= n; ++i) {
if (a[i] > k % (long long)pow(10, int(log10(a[i]) + 1))) {
ans += upper_bound(a + i + 1, a + n + 1, k / (long long)pow(10, int(log10(a[i]) + 1)) - 1) - 1 - a - i;
ans += upper_bound(a + 1, a + i, k / (long long)pow(10, int(log10(a[i]) + 1)) - 1) - 1 - a;
} else {
ans += upper_bound(a + i + 1, a + n + 1, k / (long long)pow(10, int(log10(a[i]) + 1))) - 1 - a - i;
ans += upper_bound(a + 1, a + i, k / (long long)pow(10, int(log10(a[i]) + 1))) - 1 - a;
}
}
cout << ans << endl;
return 0;
}