[bzoj3193][JLOI2013]地形生成_排列组合_贪心

[JLOI2013]地形生成

题目链接https://www.lydsy.com/JudgeOnline/problem.php?id=3193


题解

这种求总排列的题,一种常规做法就是所有的元素按照某种排列方式然后一个一个往里插。

这个题就是从大到小排序这样,对后面的元素没有影响。

现在有一些相等的元素我们怎么弄?

如果是标号序列的话,就是瞎$jb$排就行了。

如果是等高线序列的话,只要按照$a$作为第二关键字就好。

代码

#include <bits/stdc++.h>

#define N 1010 

using namespace std;

const int mod = 2011 ;

char *p1, *p2, buf[100000];

#define nc() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 100000, stdin), p1 == p2) ? EOF : *p1 ++ )

int rd() {
    int x = 0, f = 1;
    char c = nc();
    while (c < 48) {
        if (c == '-')
            f = -1;
        c = nc();
    }
    while (c > 47) {
        x = (((x << 2) + x) << 1) + (c ^ 48), c = nc();
    }
    return x * f;
}

struct Node {
    int h, rk;
}a[N];

int dp[N];

inline bool cmp(const Node &a, const Node &b) {
    return a.h == b.h ? a.rk < b.rk : a.h > b.h;
}

int main() {
    int n = rd();
    for (int i = 1; i <= n; i ++ ) {
        a[i].h = rd(), a[i].rk = rd() - 1;
    }
    int ans1 = 1, ans2 = 1;
    sort(a + 1, a + n + 1, cmp);
    for (int i = 1; i <= n; i ++ ) {
        int dic = i;
        while (dic <= n && a[dic].h == a[i].h) {
            dic ++ ;
        }
        dic -- ;
        memset(dp, 0, sizeof dp);
        dp[0] = 1;
        for (int j = i; j <= dic; j ++ ) {
            ans1 = ans1 * (min(i, a[j].rk + 1) + j - i) % mod;
            for (int k = 1; k <= min(a[j].rk, i - 1); k ++ ) {
                dp[k] = (dp[k - 1] + dp[k]) % mod;
            }
        }
        int sum = 0;
        for (int j = 0; j <= min(a[dic].rk, i - 1); j ++ ) {
            (sum += dp[j]) %= mod;
        }
        (ans2 *= sum) %= mod;
        i = dic;
    }
    cout << ans1 << ' ' << ans2 << endl ;
    return 0;
}

小结:记得,考虑问题的时候把当前时间戳这个容易忽略的变量也考虑进去,尽管大部分时候都用不到。

posted @ 2019-08-29 18:39  JZYshuraK_彧  阅读(187)  评论(0编辑  收藏  举报