给出 M M M 个个位数。现在你要用它们构造一个最短的数字串,使得这个串所有长度为 N N N 的连续子串,至少有 K K K 种。
保证存在长度在 1e5 以内的答案。
N ≤ 1 0 5 , M ≤ 10 , K ≤ min ( M N , 1 0 5 ) N\leq10^5,~M\leq10,~K\leq \min(M^N,10^5) N≤105, M≤10, K≤min(MN,105)
“这是我初二时的 GDOI 题。”
——1队dalao
\\
\\
\\
要想到,一个子串后面添加一个数字成为下一个子串,这个类似于点通过边来转移,因此用欧拉路径来建图。
考虑当 N N N 很小的时候。
把所有长度为 N − 1 N-1 N−1 的串视为点,表示子串的最后 N − 1 N-1 N−1 位。共有 M N − 1 M^{N-1} MN−1 个点。那么点与点之间就可以连转移边了,连边表示状态转移,比如 123 123 123 连一条权值为 4 4 4 的边到 234 234 234 去。
对这个图跑一次欧拉路径,那么每个点加上它连出去的边,就是题目要求的一个子串,而且都是不同的,因此总的串就是最短的。
N N N 很大的时候呢,
找到最小的 N ′ N' N′,使得 M N ′ ≥ K M^{N'}\geq K MN′≥K。那么对于所有长度为 N N N 的子串,只看最后 N ′ N' N′ 位也足够满足 K K K 的要求了,换句话说前 N − N ′ N-N' N−N′ 位是无关紧要的。因此把 N N N 换成 N ′ N' N′ 按上面的做法做就行了。
// 这个代码在 opentrain 上能过,在 cf 上会神奇地 WA 样例,似乎是搞爆了它的 spj ??
#include
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
typedef long long LL;
const int maxtot=1e6+5, maxnp=30, maxn=1e5+5;
const LL mo=1e9+7, px=998244353;
int n,m,k,np,a[15];
LL mm,powpx[maxnp];
unordered_map<LL,int> M;
int tot;
vector<pair<int,int>> e[maxtot];
void dfs1(int k,LL now)
{
if (k==np)
{
M[now]=++tot;
return;
}
fo(i,1,m) dfs1(k+1,(now*px+a[i])%mo);
}
void dfs2(int k,LL now,int fir)
{
if (k==np)
{
int my=M[now];
fo(i,1,m)
{
int go=M[((now*px+a[i]-fir*powpx[np-1])%mo+mo)%mo];
e[my].push_back(make_pair(go,a[i]));
}
return;
}
fo(i,1,m) dfs2(k+1,(now*px+a[i])%mo,(fir==-1)?a[i]:fir);
}
int nowh[maxn],d0,st,d[maxn];
void Euler(int k,int lim)
{
int sz=e[k].size();
for(int i=nowh[k]; i<sz; i=nowh[k])
{
nowh[k]=i+1;
Euler(e[k][i].first,lim);
if (d0==lim) return;
d[++d0]=e[k][i].second;
st=k;
if (d0==lim) return;
}
}
int rc[maxn];
bool pd;
void dfs3(int k,LL now)
{
if (k==np)
{
if (M[now]==st)
{
fo(i,1,np-1) printf("%d",rc[i]);
pd=1;
}
return;
}
fo(i,1,m)
{
rc[k]=a[i];
dfs3(k+1,(now*px+a[i])%mo);
if (pd) return;
}
}
int main()
{
scanf("%d %d %d",&n,&m,&k);
fo(i,1,m) scanf("%d",&a[i]);
for(np=1, mm=m; mm<k; np++, mm*=m);
powpx[0]=1;
fo(i,1,np) powpx[i]=powpx[i-1]*px%mo;
dfs1(1,0);
dfs2(1,0,-1);
Euler(1,k);
fo(i,1,n-np) printf("%d",a[1]);
dfs3(1,0);
fd(i,d0,1) printf("%d",d[i]);
}