dp套dp
我们先说一下
感性理解一些,你现在有一个动态规划数组
事实上,这个
游园会
首先最长公共子序列的动态规划是好做的,这里就不说了。
这里设最长公共子序列的动态规划数组为
我们先设
但是你发现
显然有
但是你又发现,我们知道
然后是我们的
代码:
#include<bits/stdc++.h>
#define int long long
#define mod 1000000007
#define N 40005
using namespace std;
int n,k,f[2][N][3],g[2][20],cnt[N],res[20];
char s[20];
void solve1(int state){
memset(g[0],0,sizeof g[0]);
for(int i=0;i<k;i++){
g[0][i+1]=state>>i&1;
}
for(int i=1;i<=k;i++){
g[0][i]+=g[0][i-1];
}
}
int solve2(){
int state=0;
for(int i=1;i<=k;i++){
int x=g[1][i]-g[1][i-1];
state|=x*(1<<i-1);
}
return state;
}
void solve(int cur,int state,char c,int now,int las){
if(las==0)return;//没有贡献不用转移
if(c=='I'&&now==2)return;//包含了子串NOI
int ne=c=='N'?1:0;//如果是N,下一个就从I匹配,否则从N
if(now==0&&c=='N')ne=1;//如果当前应匹配第0个且是N,后跳一位
else if(now==1&&c=='O')ne=2;//同上
solve1(state);//把差分记录的状态还原
memset(g[1],0,sizeof g[1]);//先清空
for(int i=1;i<=k;i++){
if(s[i]==c){//如果s_i=t_j,可以使用特殊转移
g[1][i]=max(g[1][i],g[0][i-1]+1);//这里的g_{0,i-1}就是lcs_{i-1,j-1}
}
g[1][i]=max({g[1][i],g[0][i],g[1][i-1]});//否则使用一般转移(g_{0,i}就是lcs_{i,j-1},g_{1,i-1}就是lcs_{i-1,j}
}
int res=solve2();//再把当前数组弄成差分状态存进去
(f[cur][res][ne]+=las)%=mod;//继承上一个
}
signed main(){
cin>>n>>k>>s+1;
int cur=0;
f[0][0][0]=1;
for(int i=1;i<=n;i++){
cur^=1;
memset(f[cur],0,sizeof f[cur]);
for(int j=0;j<1<<k;j++){
for(int p=0;p<3;p++){
char c=p==0?'N':p==1?'O':'I';
solve(cur,j,c,0,f[cur^1][j][0]);
solve(cur,j,c,1,f[cur^1][j][1]);
solve(cur,j,c,2,f[cur^1][j][2]);
}
}
}
for(int i=1;i<1<<k;i++){
cnt[i]=cnt[i>>1]+(i&1);//cnt是这个数二进制表示有几个1,这里有几个1代表lcs长度就是几
}
for(int i=0;i<1<<k;i++){
for(int j=0;j<3;j++){
(res[cnt[i]]+=f[cur][i][j])%=mod;
}
}
for(int i=0;i<=k;i++){
cout<<res[i]<<'\n';
}
return 0;
}
小 N 的独立集
独立集是指,一堆点他们两两之间没有边。最大权独立集是指,所有的独立集中,权值之和最大的那个。
这道题我们从部分分说起。
枚举所有可能的权值分配。然后参照这道题写个动态规划就行了。
首先
我们考虑将
设
我们枚举
于是有
上述转移无法通过的一个重要原因是,我们的状态复杂度过高,所以我们要优化状态。
我们重新定义
于是
此时复杂度
代码:
#include<bits/stdc++.h>
#define int long long
#define N 1005
#define M 2009
#define mod 1000000007
using namespace std;
int n,k,siz[N];
int f[N][N*6][6],g[N*6][6];
int h[N],e[M],ne[M],idx;
void add(int a,int b){
e[idx]=b;ne[idx]=h[a];h[a]=idx++;
}
void dfs(int u,int fa){
siz[u]=1;
for(int i=1;i<=k;i++){
f[u][0][i]=1;
}
for(int a=h[u];~a;a=ne[a]){
int v=e[a];
if(v==fa)continue;
dfs(v,u);
memset(g,0,sizeof g);
for(int i=0;i<=k*siz[u];i++){
for(int j=0;j<=k;j++){
if(f[u][i][j]==0)continue;
for(int p=0;p<=k*siz[v];p++){
for(int q=0;q<=k;q++){
if(f[v][p][q]==0)continue;
int &t=g[i+p+q][max(i+j+p,i+p+q)-(i+p+q)];
(t+=f[u][i][j]*f[v][p][q]%mod)%=mod;
}
}
}
}
memcpy(f[u],g,sizeof g);
siz[u]+=siz[v];
}
}
signed main(){
cin>>n>>k;
memset(h,-1,sizeof h);
for(int i=1;i<n;i++){
int a,b;
cin>>a>>b;
add(a,b);add(b,a);
}
dfs(1,0);
for(int i=1;i<=k*n;i++){
int res=0;
for(int j=0;j<=min(i,k);j++){
(res+=f[1][i-j][j])%=mod;
}
cout<<res<<'\n';
}
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探