原题地址: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[i−1][j]+dp[i−1][j−1]∗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;
}