Excavations

dp #性质

一个集合 \(s\) 满足条件,当且仅当 \(\forall x\in s, mindep_x<min_{y\notin s}mindep_y\)

枚举后面的那个,\(dp_i\) 表示前面选择 \(i\) 个的方案数,转移看code

// Author: xiaruize
const int N = 50 + 10;

int n, k;
struct node
{
    int kd, dep;
} s[N];
int m;
bool vis[N];
int cnt[N], cur[N];
int dp[N];
int tot = 0;
int c[N][N];
int tmp[N];

bool cmp(node a, node b)
{
    if (a.dep != b.dep)
        return a.dep < b.dep;
    return vis[a.kd] < vis[b.kd];
}

void solve()
{
    cin >> n;
    rep(i, 1, n)
    {
        cin >> s[i].kd;
        cnt[s[i].kd]++;
        tot = max(tot, s[i].kd);
    }
    cin >> n;
    rep(i, 1, n) cin >> s[i].dep;
    cin >> m;
    rep(i, 1, m)
    {
        int x;
        cin >> x;
        vis[x] = true;
    }
    rep(i, 0, 50)
    {
        c[i][0] = c[i][i] = 1;
        rep(j, 1, i - 1)
            c[i][j] = c[i - 1][j] + c[i - 1][j - 1];
    }
    cin >> k;
    sort(s + 1, s + n + 1, cmp);
    int res = 0;
    rep(i, 1, n)
    {
        cnt[s[i].kd]--;
        if (!vis[s[i].kd])
            continue;
        mms(dp, 0);
        dp[1] = 1;
        rep(j, 1, tot)
        {
            memcpy(tmp, dp, sizeof(dp));
            mms(dp, 0);
            rep(p, 1, k)
            {
                rep(q, 0, min(cnt[j], k - p))
                {
                    dp[p + q] += c[cnt[j]][q] * tmp[p];
                }
            }
            if (vis[j] && s[i].kd != j)
            {
                memcpy(tmp, dp, sizeof(dp));
                mms(dp, 0);
                rep(p, 1, k)
                {
                    rep(q, 1, min(cur[j], k - p))
                    {
                        dp[p + q] += c[cur[j]][q] * tmp[p];
                    }
                }
            }
        }
        cur[s[i].kd]++;
        res += dp[k];
    }
    cout << res << endl;
}

#ifndef ONLINE_JUDGE
bool end_of_memory_use;
#endif

signed main()
{
    // freopen(".in","r",stdin);
    // freopen(".out","w",stdout);
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);
    int testcase = 1;
    // cin >> testcase;
    while (testcase--)
        solve();
#ifndef ONLINE_JUDGE
    cerr << "Memory use:" << (&end_of_memory_use - &start_of_memory_use) / 1024.0 / 1024.0 << "MiB" << endl;
    cerr << "Time use:" << (double)clock() / CLOCKS_PER_SEC * 1000.0 << "ms" << endl;
#endif
    return 0;
}
posted @ 2024-04-10 10:12  xiaruize  阅读(11)  评论(0)    收藏  举报