0%

Edu-CF-184-D2. Removal of a Sequence (Hard Version)(如何优化这个多次的向下取整触发/向下取整分数,)

题目大意

这是问题的简单版本。版本之间的区别在于xx的约束;在这个版本中,x105x \le 10^5

Polycarp有一个包含从11101210^{12}的所有自然数的序列。他决定通过执行以下操作$ x $次来修改这个序列:

  • 同时删除所有在位置yy2y2 \cdot y3y3 \cdot y,…,mynm \cdot y \le n的数字,其中$ n $是当前序列的长度。

之后,Polycarp想要在剩余序列中找到第$ k 个数字,或确定结果序列的长度小于个数字,或确定结果序列的长度小于 k $。

帮助Polycarp解决这个问题!

考虑一个例子。假设$ x = 2 y = 3 k = 5 $,那么:

image

红线划掉的数字在第一次操作后被删除,蓝线划掉的数字在第二次操作后被删除。因此,位置$ k = 5 处的数字是数字处的数字是数字 10 $。

思路讲解


我们直接使用这个第一问当中的这个 check 函数,由于其是 O(X)O(X),会超时。我们也可以优化这个二分检查器代码,让其一次性把 subtractlenysubtract\gets \lfloor \frac{len}{y}\rfloor 相同的一起处理。这样子,使用二分的复杂度就是 O(AlogA)O(\sqrt A \log A),其中 A\sqrt A 是一个数字能够拥有的这个因数数量量级。

不过题目作者专门卡了我们二分答案一手,因此必须采用逆向还原的思路。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
for (ll i=1;i<=X;++i) {
ll subtract=0;
if (len%(Y-1)==0) {
subtract=len/(Y-1)-1;
len+=subtract;
}else {
subtract=len/(Y-1);
ll dis=((Y-1)*(subtract+1))-len;
ll cnt=(dis+subtract-1)/subtract;
cnt=min(X-i+1,cnt);
i+=cnt-1;
len+=cnt*subtract;
}
if (len>(ll)1e12) {
cout<<-1<<"\n";
return;
}
}

逆向还原,我们知道,每出现 y1y-1 个数字,那么就代表有一个数字被删除了,那么一次需要增长的长度就是 leny1\lfloor \frac{len}{y-1} \rfloor

这里有一个比较阴的特殊情况,就是 len0(mody1)len \equiv 0 \pmod {y-1},这个时候,能够增长的长度就是只有 leny11\lfloor \frac{len}{y-1} \rfloor-1

我们可以就像最简单的,当序列长度为 y1y-1,其达到 y1y-1 需要多少长度,是 yy 吗?显然不是,其需要增长的就是 0 长度。

我们和优化二分的时候采用一样的思路,每次增长相同长度的,一起操作,这样子时间复杂度就是 O(A)O(\sqrt A)

具体而言,就是先计算需要增长的长度 subtractsubtract,然后计算需要能够以 subtractsubtract 继续增长的次数,即 cntcnt,然后 cntmin(cnt,Xi+1)cnt\gets \min(cnt,X-i+1),避免加上 cntcnt 超过操作次数限制。不断重复这个过程,直到达到操作次数 XX

AC代码

AC
https://codeforces.com/contest/2169/submission/360686378

TLE

https://codeforces.com/contest/2169/submission/360461585

心路历程(WA,TLE,MLE……)