题目
思路/实现过程
首先可以发现包含关系显然可以去掉
很容易想到一个类似
f
i
,
j
f_{i,j}
fi,j 前
i
i
i 个,(
i
i
i 到
i
+
1
i+1
i+1 有
j
j
j 个
1
1
1) 之类的
d
p
dp
dp 定义
但是发现不好打,而且思路比较混乱
我们可以将操作区间处理成前缀做差
具体而言
n
x
t
nxt
nxt 表示添加了一个
[
n
x
t
i
−
1
+
1
,
n
x
t
i
]
[nxt_{i-1}+1,nxt_i]
[nxti−1+1,nxti] 的操作区间
然后我们定义
d
p
dp
dp 状态
f
i
,
j
f_{i,j}
fi,j 前
i
i
i 个数放置后,还能放
j
j
j 个
1
1
1 的方案数
f[0][s[nxt[1]]]=1;
for(int i=1;i<=n;i++){
int t=s[nxt[i+1]]-s[nxt[i]];
for(int j=0;j<=nxt[i]-i;j++)
f[i][j+t]=Add(f[i-1][j],f[i-1][j+1]);
}
我们仔细捋一捋上述代码
代码
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<vector>
#include<cmath>
#include<cstring>
#include<cstdio>
#include<climits>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
#define LL long long
int read(){
int f=0,x=0;char c=getchar();
while(c<'0'||'9'<c){if(c=='-')f=1;c=getchar();}
while('0'<=c&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
return !f?x:-x;
}
#define mp make_pair
const int MAXN=3000;
const int INF=0x3f3f3f3f;
const int Mod=(int)(1e9+7);
int Add(int x,int y){x+=y;return x>=Mod?x-Mod:x;}
char str[MAXN+5];
int f[MAXN+5][MAXN+5],s[MAXN+5],nxt[MAXN+5];
int main(){//f[i][j]:前i个放好后,还有j个1能放的方案数
int n=read(),m=read();
scanf("%s",str+1);
for(int i=1;i<=n+1;i++)
s[i]=s[i-1]+(str[i]=='1');
for(int i=1;i<=n+1;i++)
nxt[i]=i;
for(int i=1;i<=m;i++){
int l=read(),r=read();
nxt[l]=max(nxt[l],r);
}
for(int i=1;i<=n;i++)
nxt[i]=max(nxt[i],nxt[i-1]);
f[0][s[nxt[1]]]=1;
for(int i=1;i<=n;i++){
int t=s[nxt[i+1]]-s[nxt[i]];
for(int j=0;j<=nxt[i]-i;j++)
f[i][j+t]=Add(f[i-1][j],f[i-1][j+1]);
}
printf("%d\n",f[n][0]);
return 0;
}