题解 昵称

传送门

  • 一些方案数会爆 long long 但我们只需知道它是否 > 某个数的情况下我们可以让这个方案数时刻对 1e18 取 min

\(s\) 弄那么大似乎没什么用,不影响数位 DP
\(f_{i, j}\) 为考虑到第 \(i\) 位,与 \(s\) 匹配长度为 \(j\) 的方案数
这里转移需要 kmp 自动机优化
最后按位确定即可
话说 0 有前导 0 吗?
复杂度大约 \(O((|s|)^2\log n)\)

点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 2050
#define ll long long
#define int long long
#define int128 __int128
#define ull unsigned long long

int n, m;
char s[N];

namespace force{
	char sta[N], top;
	ull h[N], pw[N], tem;
	const ull base=13131;
	inline ull hashing(int l, int r) {return h[r]-h[l-1]*pw[r-l+1];}
	bool check(int t) {
		top=0;
		do {sta[++top]=t%10; t/=10;} while (t);
		reverse(sta+1, sta+top+1);
		for (int i=1; i<=top; ++i) h[i]=h[i-1]*base+sta[i];
		for (int i=m; i<=top; ++i) if (hashing(i-m+1, i)==tem) return 1;
		return 0;
	}
	void solve() {
		pw[0]=1;
		for (int i=1; i<N; ++i) pw[i]=pw[i-1]*base;
		for (int i=1; i<=m; ++i) tem=tem*base+s[i];
		for (int i=0; ; ++i) {
			if (check(i)) --n;
			if (!n) {cout<<i<<endl; break;}
		}
	}
}

namespace task1{
	ll ans[N];
	int nxt[N], tran[N][12];
	int128 dp[N][N], pw[N];
	int128 dfs(int u, int k) {
		if (k==m) return pw[u];
		if (!u) return 0;
		if (~dp[u][k]) return dp[u][k];
		int128* t=&dp[u][k]; *t=0;
		for (int i=0; i<10; ++i) {
			// int len=k;
			// while (len && i!=s[len+1]) len=nxt[len];
			// if (i==s[len+1]) ++len;
			int len=tran[k][i];
			*t+=dfs(u-1, len);
		}
		return *t;
	}
	void solve() {
		memset(dp, -1, sizeof(dp));
		pw[0]=1;
		for (int i=1; i<=50; ++i) pw[i]=pw[i-1]*10;
		nxt[1]=0;
		for (int i=2,j=0; i<=m; ++i) {
			while (j && s[j+1]!=s[i]) j=nxt[j];
			if (s[j+1]==s[i]) ++j;
			nxt[i]=j;
		}
		for (int i=0; i<=m; ++i)
			for (int j=0; j<10; ++j)
				if (s[i+1]==j) tran[i][j]=i+1;
				else tran[i][j]=tran[nxt[i]][j];
		int k=0;
		for (int i=m+25; i; --i) {
			// cout<<"i: "<<i<<endl;
			if (k==m) {
				int top=0;
				--n;
				while (n) {ans[++top]=n%10; n/=10;}
				break;
			}
			for (int j=0; j<10; ++j) {
				// int len=k;
				// while (len && j!=s[len+1]) len=nxt[len];
				// if (j==s[len+1]) ++len;
				int len=tran[k][j];
				int128 t=dfs(i-1, len);
				// cout<<"j: "<<j<<' '<<n<<' '<<(ll)t<<endl;
				// cout<<"dfs: "<<i-1<<' '<<(len)<<endl;
				if (n>t) n-=t;
				else {
					ans[i]=j;
					k=len;
					break;
				}
			}
		}
		int pos=m+25;
		while (pos>1 && !ans[pos]) --pos;
		for (int i=pos; i; --i) printf("%lld", ans[i]); printf("\n");
	}
}

signed main()
{
	freopen("nickname.in", "r", stdin);
	freopen("nickname.out", "w", stdout);

	scanf("%s%lld", s+1, &n);
	m=strlen(s+1);
	for (int i=1; i<=m; ++i) s[i]-='0';
	// force::solve();
	task1::solve();
	
	return 0;
}
posted @ 2022-03-03 21:28  Administrator-09  阅读(2)  评论(0编辑  收藏  举报