2018-2019 ACM-ICPC Pacific Northwest Regional Contest C Contest Setting(DP)

比赛链接:Contest Setting C题

题意:$n$道题目,每道题目难度为$ai$,选择$k$道难度不同的题目,有多少种选择方案。$1<=k<=n<=1000,1<=ai<=10^9$ 

题解:问题转化一下(map,离散化均可):m种难度,每种难度有bi道题目,每次从m种中选择k种,把对应的题目数量相乘,求总和。

列出$dp[i][j]$:表示前j个物品以j结尾选择i个的方案数;$sum[i][j]$:表示从1-j分别作为结尾选择i个的方案数总和。

$dp[i][j]=b[j]*sum[i-1][j-1]$

$sum[i][j]=sum[i][j-1]+dp[i][j]$

 1 #include <map>
 2 #include <cstdio>
 3 #include <vector>
 4 #include <cstring>
 5 #include <iostream>
 6 #include <algorithm>
 7 using namespace std;
 8 
 9 const int N=1e3+10;
10 typedef long long ll;
11 const ll mod=998244353;
12 map <ll,ll> m;
13 vector <ll> v;
14 ll b[N],dp[N][N],sum[N][N];
15 
16 int main(){
17     int n,k;
18     ll x;
19     scanf("%d%d",&n,&k);
20     for(int i=1;i<=n;i++){
21         scanf("%lld",&x);
22         if(m[x]==0) v.push_back(x);
23         m[x]++;
24     }
25     n=v.size();
26     for(int i=1;i<=n;i++) b[i]=m[v[i-1]];
27     for(int i=1;i<=n;i++) dp[1][i]=b[i]%mod,sum[1][i]=(dp[1][i]+sum[1][i-1])%mod;
28     for(int i=2;i<=k;i++){
29         for(int j=1;j<=n;j++){
30             dp[i][j]=(b[j]*sum[i-1][j-1])%mod;
31             sum[i][j]=(dp[i][j]+sum[i][j-1])%mod;
32         }
33     }
34     printf("%lld\n",sum[k][n]);
35     return 0;
36 }
View Code

 

posted @ 2018-11-14 15:56  pavtlly  阅读(583)  评论(0编辑  收藏  举报