B
思路
设是前个元素的方案数。考虑第个元素,在它前面的某个元素的后面插一个板,在的元素后面不插板,此时对答案的贡献就是。这样可以一直插到哪里呢?如果第个元素在中出现过,那就不可能再往前找了,因为后面必然要插一个板。
维护以第个元素结尾的最长的不含重复元素的连续子序列长度,记为。根据上文可知,。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
typedef long long ll;
typedef double db;
using namespace std;
const ll INF=0x3f3f3f3f;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const ll N=1E4+10,P=1E9+7;
ll n,Left=1;
ll vis[20],f[N],dp[N];
string s;
void print()
{
rep(i,1,n)
cout<<f[i]<<" ";
cout<<endl;
}
int main()
{
In(1,&n);
cin>>s;
s=' '+s;
rep(i,1,n)
{
while(vis[s[i]-'0'])
{
--vis[s[Left]-'0'];
++Left;
}
++vis[s[i]-'0'];
f[i]=i-Left+1;
}
dp[0]=1;
rep(i,1,n)
rep(j,1,f[i])
dp[i]=(dp[i]+dp[i-j])%P;
Out(1,dp[n]);
}
J
思路
设为第个串接在第个串之后重合的最大长度,暴力搜索所有可能性即可。
直接暴力搜会T,考虑记忆化搜索。设为最后一个串是第个串,的二进制位为每个串的使用情况的整个串的最小长度。只有当前的长度小于的时候才继续往下搜。
一个细节是如果把接在后面,恰好完全包含,那此时的最后一个串仍是,需要特判一下。
代码
#include<bits/stdc++.h>
#define rep(i,st,ed) for(int i=st;i<=ed;++i)
#define bl(u,i) for(int i=head[u];i;i=e[i].nxt)
#define LLM LONG_LONG_MAX
#define LLm LONG_LONG_MIN
#define pii pair<ll,ll>
#define tst
typedef long long ll;
typedef double db;
using namespace std;
const int INF=0x3f3f3f3f;
inline void In(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
scanf("%lld",va_arg(lis,ll*));
}
inline void Out(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld\n",va_arg(lis,ll));
}
inline void Out_(ll _,...)
{
va_list lis;
va_start(lis,_);
while(_--)
printf("%lld ",va_arg(lis,ll));
}
const int N=16,M=101;
int n,ans=INF,rec;
int a[N][M],t[N][N],vis[N],f[N][1<<16];
#ifdef tst
void dfs(int lst,int tot)
{
if(f[lst][rec]<=tot && f[lst][rec]!=0)
return;
f[lst][rec]=tot;
if(tot>ans)
return;
int flag=0;
rep(i,1,n)
{
if(vis[i])
continue;
flag=1;
rec+=1<<(i-1);
vis[i]=1;
if(a[i][0]==t[lst][i])
dfs(lst,tot);
dfs(i,tot+a[i][0]-t[lst][i]);
vis[i]=0;
rec-=1<<(i-1);
}
if(!flag)
ans=min(ans,tot);
}
#endif
void print()
{
rep(i,1,n)
{
rep(j,1,n)
cout<<i<<" "<<j<<" "<<t[i][j]<<endl;
}
}
int main()
{
scanf("%d",&n);
rep(i,1,n)
{
scanf("%d",&a[i][0]);
rep(j,1,a[i][0])
scanf("%d",&a[i][j]);
}
rep(i,1,n)
{
rep(j,1,n)
{
if(i==j)
continue;
rep(k,1,a[i][0])
{
if(a[i][k]==a[j][1])
{
int indx=k,indy=1;
int tog=1;
while(indx<a[i][0] && indy<a[j][0])
{
if(a[i][indx+1]!=a[j][indy+1])
{
tog=0;
break;
}
++indx;
++indy;
++tog;
}
if(indx==a[i][0] || indy==a[j][0])
{
t[i][j]=tog;
break;
}
}
}
}
}
#ifdef tst
rep(i,1,n)
{
vis[i]=1;
rec+=1<<(i-1);
dfs(i,a[i][0]);
rec-=1<<(i-1);
vis[i]=0;
}
#endif
cout<<ans<<endl;
}