Gym - 101982 C - Contest Setting(dp)

原题地址:http://codeforces.com/gym/101982/attachments

题意:有n个题目,每个题目有一个难度系数,现在要用其中k个题目组成一套卷子,要求

卷子中每一道题的难度系数不同,问最后的方案数。
思路:一开始以为是组合数,但是发现不会写。后来考虑用 d p dp dp来写。定义 d p [ i ] [ j ] dp[i][j] dp[i][j]表示选用前 i i i种难度的题目,选出 j j j个题目的方案数。那么 d p dp dp转移方程就和背包的转移有点像, d p [ i ] [ j ] = d p [ i − 1 ] [ j ] + d p [ i − 1 ] [ j − 1 ] ∗ v a l [ i ] dp[i][j]=dp[i-1][j]+dp[i-1][j-1]*val[i] dp[i][j]=dp[i1][j]+dp[i1][j1]val[i] ( v a l [ i ] val[i] val[i]表示难度为i的题目数量)。

需要注意的是题目数据范围有1e9,需要用map去存。

#include 
#define eps 1e-8
#define INF 0x3f3f3f3f
#define PI acos(-1)
#define lson l,mid,rt<<1
#define rson mid+1,r,(rt<<1)+1
#define CLR(x,y) memset((x),y,sizeof(x))
#define fuck(x) cerr << #x << "=" << x << endl
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const int seed = 131;
const int maxn = 1e5 + 5;
const int mod = 998244353;
map<int, int>mp;
vector<int>v;
ll n, k;

ll dp[1005][1004];
int main() {
    scanf("%lld%lld", &n, &k);
    for (int i = 1; i <= n; i++) {
        int  x;
        scanf("%d", &x);
        mp[x]++;
    }
    CLR(dp, 0);
    dp[0][0] = 1;
    map<int, int>::iterator it;
    int  i = 1;
    for (it = mp.begin(); it != mp.end(); it++) {
        int x1 = it->first;
        int x2 = it->second;
        for (int j = 0; j <= k; j++) {
            dp[i][j] = (dp[i][j] + dp[i - 1][j]) % mod;
            if (j != 0)dp[i][j] = (dp[i][j] + dp[i - 1][j - 1] * x2) % mod;
        }
        i++;
    }
    printf("%lld\n", dp[i - 1][k]);
    return 0;
}



你可能感兴趣的:(ACM_DP)