P15650 题解
DaiRuiChen007 · · 题解
Problem Link
一个比较好写且常数比较小的做法。
首先考虑如何数
考虑增量,从
把
显然只要记录第一类的数量
如果总数为
那么直接记录
考虑优化掉
所以只要知道串长
直接把 dp 过程转置,从后往前插入
对 bitset 优化
时间复杂度
代码:
#include<bits/stdc++.h>
using namespace std;
int n,K,fa[205],e[205][2],w[205][2],d[205];
bitset <3005> f[3415][2][205],tf;
void solve() {
string s;
cin>>n>>K>>s,s=" "+s;
for(int i=2,j=0;i<=n;++i) {
for(;j&&s[j+1]!=s[i];j=fa[j]);
fa[i]=j+=(s[j+1]==s[i]);
}
for(int i=1;i<=n;++i) d[i]=d[fa[i]]+(i<n);
for(int i=0;i<=n;++i) for(int c:{0,1}) {
int j=i;
for(;j&&(j==n||s[j+1]!=c+'0');j=fa[j]);
e[i][c]=j+(s[j+1]==c+'0'),w[i][c]=0;
for(int x=i;;x=fa[x]) {
w[i][c]+=x<n&&s[x+1]>c+'0';
if(!x) break;
}
}
for(int x=0;x<=n;++x) {
f[0][0][x].reset(),f[0][1][x].reset();
f[0][x==n][x][K]=1;
}
for(int i=1;i<=K+n*2+5;++i) {
bool op=0;
for(int x=0;x<=n;++x) {
f[i][0][x].reset(),f[i][1][x].reset();
for(int o:{0,1}) for(int c:{0,1}) {
int v=w[x][c]*i+d[e[x][c]];
if(v>K) continue;
tf=f[i-1][o][e[x][c]],tf>>=v,f[i][o||x==n][x]|=tf;
}
op|=f[i][0][x].any()||f[i][1][x].any();
}
if(f[i][1][0][0]) {
string ans="";
for(int j=i-1,x=0,y=0,o=0;~j;--j) {
o|=x==n;
for(int c:{0,1}) {
int v=w[x][c]*(j+1)+d[e[x][c]];
if(y+v>K) continue;
if(f[j][1][e[x][c]][y+v]||(o&&f[j][0][e[x][c]][y+v])) { x=e[x][c],y+=v,ans+=c+'0'; break; }
}
}
return cout<<ans<<"\n",void();
}
if(!op) break;
}
cout<<"Impossible\n";
}
signed main() {
ios::sync_with_stdio(false),cin.tie(0),cout.tie(0);
int ty,_; cin>>ty>>_;
while(_--) solve();
return 0;
}