1 条题解
-
0
自动搬运
来自洛谷,原作者为

Purslane
AFO搬运于
2025-08-24 23:14:19,当前版本为作者最后更新于2025-04-23 16:39:16,作者可能在搬运后再次修改,您可在原文处查看最新版自动搬运只会搬运当前题目点赞数最高的题解,您可前往洛谷题解查看更多
以下是正文
Solution
本题的含义是,对于所有的方案最终药水的权值求和。
设全集 ,定义其子集 的权值为 。
对于一种局面,他最终的药水魔法值一定可以写成 ,其中 。
而对所有可能的方案求和后,答案一定也可以写成 。每个数的地位是相同的,所以 一定只和 有关。
因此我们只需要能够算出,每个集合能在多少种方案中得出即可。
考虑 DP。设 表示,全集大小为 ,一个大小为 的子集能通过多少种方式被合成。我们可以将操作改写成:选择两个药品,丢弃掉一个,或者将他们合并。
我们只能丢弃掉最终不要的药品,以及合并需要的药品。
很容易 处理出这个东西。
剩下的问题就是:如何求出 。由于 的定义是乘积,这个也很容易用 DP 处理。
总体复杂度 ,足以通过本题。代码极其短。
注:我最开始用了二十分钟去想 如何转移。因为我思考的主体是“将一种个问题分成两个子问题并且合并”,但是在这道题中完全不适用。
ヾ(。`Д´。)ノ彡
#include<bits/stdc++.h> #define int long long #define ffor(i,a,b) for(int i=(a);i<=(b);i++) #define roff(i,a,b) for(int i=(a);i>=(b);i--) using namespace std; const int MAXN=3000+10; int n,ans,a[MAXN],MOD,dp[MAXN][MAXN],mul[MAXN]; signed main() { ios::sync_with_stdio(false),cin.tie(0),cout.tie(0); cin>>n>>MOD; dp[1][1]=1; ffor(i,2,n) ffor(j,1,i) dp[i][j]=((i-j)*(i-1)*dp[i-1][j]+j*(j-1)/2*dp[i-1][j-1])%MOD; mul[0]=1; ffor(i,1,n) { cin>>a[i]; roff(j,n,1) mul[j]=(mul[j]+mul[j-1]*a[i])%MOD; } ffor(i,1,n) ans=(ans+mul[i]*dp[n][i])%MOD; cout<<ans; return 0; }
- 1
信息
- ID
- 12140
- 时间
- 3000ms
- 内存
- 512MiB
- 难度
- 6
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者