【题解】P8708 题解
P8708 题解
思路分析
二分题。
证明一个小结论:
设 和 拼接小于 ,若存在 ,则 和 拼接必然小于 。
这个非常显然的其实,因为比较的时候, 部分是不影响的,所以就由 和 来决定这个大小,而 和 的大小显然,所以得证。
于是根据这个结论,我们可以认为答案具有单调性,不过是在原数组排序的前提下。
然后二分就 OK 了。我们遍历数组,每次找到最后一个和遍历到的拼接满足条件的就可以了,根据结论,那个最后一个数的下标就是答案。
但是需要注意,如果下标大于遍历到的数的下标,答案还得减去一,因为自己不能和自己拼接。
代码
#include <iostream>
#include <iomanip>
#include <cmath>
#include <string>
#include <algorithm>
#include <cstdio>
#include <cstring>
#define endl '\n'
#define int long long
#define IL inline
using namespace std;
const int N = 1e5 + 10;
const int INF = 0x3f3f3f3f;
IL int read()
{
int x = 0,f = 1;
char c = getchar();
while(c <'0'|| c >'9'){if(c == '-') f = -1;c = getchar();}
while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0',c = getchar();
return x * f;
}
void write(int x)
{
if(x < 0) putchar('-'),x = -x;
if(x > 9) write(x / 10);
putchar(x % 10 + '0');
}
int a[N];
int n, k;
bool check(int x, int y)
{
int w = log10(y) + 1;
int g = x * __builtin_fabs(10, w) + y;
return g <= k;
}
signed main()
{
ios::sync_with_stdio(0);
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);
int ans = 0;
for(int i = 1;i <= n;i++)
{
int l = 1, r = n;
while(l <= r)
{
int mid = (l + r) >> 1;
if(check(a[i], a[mid]))
{
l = mid + 1;
}
else
{
r = mid - 1;
}
}
if(r >= i) r--;
ans += r;
}
cout << ans << endl;
return 0;
}

浙公网安备 33010602011771号