CF1542D

直接计算子集 \(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;
                    }
                }
            }
posted @ 2021-07-07 22:22  ullio  阅读(59)  评论(0编辑  收藏  举报