【题解】P8708 题解

P8708 题解

思路分析

二分题。

证明一个小结论:

aacc 拼接小于 kk,若存在 bcb \leq c ,则 aabb 拼接必然小于 kk

这个非常显然的其实,因为比较的时候,aa 部分是不影响的,所以就由 bbcc 来决定这个大小,而 bbcc 的大小显然,所以得证。

于是根据这个结论,我们可以认为答案具有单调性,不过是在原数组排序的前提下。

然后二分就 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;
}                    
posted @ 2023-09-06 13:54  邻补角-SSA  阅读(8)  评论(0)    收藏  举报  来源