标签:le 个人 Two 选择 这题 ABC 238 forall dp
题目大意
有\(n\)个人参加两场比赛,第\(i\)个人在第一场比赛中的排名是\(P_i\),在第二场比赛中的排名是\(Q_i\),现在要求你选择\(k\)个人,要求\(\forall\)被选择的人\(i\)和\(\forall\)没有被选择的人,满足\(P_i>P_j\)或\(Q_i>Q_j\),问有多少种选择的方法,答案对\(998244353\)取模。\((1\le n\le300,1\le k\le n)\)
思路
这题记得寒假的时候还做过,还看过\(Solemntee\)大佬的博客,然后今天又做了一遍发现还是不会,悲。所以写一篇博客,希望下次遇到能秒。这题的话首先肯定能想到\(dp\),我们先对\(P\)进行排序,就能消除\(P\)对答案的影响,然后再设\(dp[i][j][k]\)为前\(i\)个人,选择\(j\)个人,其中最小的没被选择的排名为\(k\)的方案数。然后考虑转移:
\[\begin{cases} dp[i][j+1][k]=dp[i][j+1][k]+dp[i-1][j][k]&if\ Q_i<k\\ dp[i][j][\min(k,Q_i)]=dp[i][j][\min(k,Q_i)]+dp[i-1][j][k]&\forall i,j,k \end{cases} \]然后这道题就做完啦
代码
#include<bits/stdc++.h>
using namespace std;
struct score
{
int a,b;
bool operator<(const score& s)const
{
return a<s.a;
}
}a[305];
long long dp[305][305][305];
long long mod=998244353;
int main()
{
int n,k;
scanf("%d%d",&n,&k);
for(int i=1;i<=n;i++)scanf("%d",&a[i].a);
for(int i=1;i<=n;i++)scanf("%d",&a[i].b);
sort(a+1,a+n+1);
dp[0][0][n+1]=1;
for(int i=1;i<=n;i++)
{
for(int j=0;j<i;j++)
{
for(int l=1;l<=n+1;l++)
{
if(a[i].b<l)dp[i][j+1][l]=(dp[i][j+1][l]+dp[i-1][j][l])%mod;
dp[i][j][min(l,a[i].b)]=(dp[i][j][min(l,a[i].b)]+dp[i-1][j][l])%mod;
}
}
}
long long ans=0;
for(int i=1;i<=n+1;i++)
{
ans=(ans+dp[n][k][i])%mod;
}
printf("%lld\n",ans);
return 0;
}
标签:le,个人,Two,选择,这题,ABC,238,forall,dp 来源: https://www.cnblogs.com/Jerry-Black/p/16293957.html
本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享; 2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关; 3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关; 4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除; 5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。