决赛那天感觉确实没发挥好。本来有机会逃离三题大队的。结果中途很多人搞了几何构造题,忍不住跟风。事实证明以我的想象力果然搞不出来。还不如专心搞搞B这题。
B的题意很简单,给一个长度不超过5000的字符串,字符集大小不超过5000,求字典序第k小的子串(子串可以不连续),k规模不超过子串总数以及1E18。
先考虑每个字符都不同的情况,很容易想到一个一个把答案的字符定下来。我们每一次求出下一步接字符a[i]的子串个数,也就是2n−i2^{n-i}2n−i,那么从小到大枚举字符值x,找到第k个字符串所在的那个x即可,再让k减去这一步小于x的子串总数,进入下一步。
出现重复字符时,2n−i2^{n-i}2n−i还需要乘上一个累计值g,这个值取决于a[i]之前出现的已有字符串ans的总数。用dp来记录以i结尾的字符串ans总数,这个累计值就是dp数组的前缀和。注意如果g[n]>=k则下一个字符是空的,直接退出就好了。
由于题目没有放在OJ上,以下代码只是随便打打,题解的解释之后也会进一步补充。
自己以后思路还需要放清晰,不能在比赛的时候慌乱。
#include<cstdio>
#include<algorithm>
using namespace std;
using LL=long long;
int T,n,m,k,a[5005],ans[5005];
LL dp[5005],g[