直接计算子集 \(B\) 的 \(f(B)\) 不太现实,所以考虑计算每一个数的贡献
我们规定相同的数序号更小的数的更小
对于数 \(a_i\) ,显然对它有影响的只有所有的 "-", 它前面小于等于它的数,它后面小于它的数
所以枚举每一个数的位置 \(i\) ,考虑 \(dp_j\) 表示小于等于 \(a_i\) 的数的个数为 \(j\) 得方案数
转移方程如下
for(int i=1; i<=n; i++) {
if(a[i] != -1) {
int mx = 0;
memset(dp, 0, sizeof dp);
dp[0] = 1;
for(int j=1; j<=n; j++) {
if(j < i) {
if(a[j] == -1) {
dp[0] = (2*dp[0]) % mod;
for(int k=0; k<mx; k++)
dp[k] = (dp[k] + dp[k+1]) % mod;
}
else {
bool s = (a[j] <= a[i]);
mx += s;
for(int k=mx; k>=s; k--)
dp[k] = (dp[k] + dp[k-s]) % mod;
}
}
else if(j == i) {
mx += 1;
for(int k=mx; k; k--)
dp[k] = dp[k-1];
dp[0] = 0;
}
else {
if(a[j] == -1) {
for(int k=1; k<mx; k++)
dp[k] = (dp[k] + dp[k+1]) % mod;
}
else {
bool s = (a[j] < a[i]);
mx += s;
for(int k=mx; k; k--)
dp[k] = (dp[k] + dp[k-s]) % mod;
}
}
}