P8708 [蓝桥杯 2020 省 A1] 整数小拼接
题目:
链接:https://www.luogu.com.cn/problem/P8708
这个大佬的题解讲的很好:
我补充说明下他没讲仔细的地方:
关于p:p记录的是“后”+“前”的第一个小于等于k的位置,当p在i的右边的时候,说明多加了一个i,要减掉;
关于为什么似乎没有记录反着拼接?
比如说,1,2,3,4,5
,如果41不行,那么42肯定舍去(这是p的大+小的性质);如果上面的i轮到p的右边之后,比如i=4,p=3,那么这时相当于比较43,不行,p就往前跳。这样就不用额外反着比较。
逻辑清晰,代码精练!
而且记住stoll和stoi。
我刚开始的思路差不多,但是可能会麻烦而且容易绕弯。本来是想用二分(似乎也可以?),但是编码有点繁琐。
其实看了他的之后感觉也不会,就是把while (p >= 0 and con(lst[p], lst[i]) > k)p--;
的改成二分,左边界为l,右边界为p二分。
#include<iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<sstream>
#include<string>
#include<string.h>
#include<iomanip>
#include<stdlib.h>
#include<map>
#include<queue>
#include<limits.h>
#include<climits>
#include<fstream>
#include<stack>
typedef unsigned long long ll;
using namespace std;
const int N = 1e5 + 10;
int n;
ll k;
ll lst[N];
ll con(ll a, ll b)
{
return stoll(to_string(a) + to_string(b));
}
int main()
{
cin >> n >> k;
for (int i = 0; i < n; i++)cin >> lst[i];
sort(lst, lst + n);
int p = n - 1;
ll ans = 0;
for (int i = 0; i < n; i++)
{
while (p >= 0 and con(lst[p], lst[i]) > k)p--;
ans += p + 1;
ans -= (p >= i);
}
cout << ans;
return 0;
}