【组合数学题目】宇宙分解
【组合数学题目】宇宙分解
算法竞赛:组合数学、组合、乘法原理
题目链接:洛谷 P13550 宇宙分解
题目描述:
你有一个序列 aaa 和两种操作:
- 选择 ai<ai+1a_i<a_{i+1}ai<ai+1 并删去 ai+1a_{i+1}ai+1。
- 选择 ai<ai+1a_i<a_{i+1}ai<ai+1 并交换这两个数。
你要不断进行这两种操作,直到无法继续,求结束时会得到多少种本质不同的序列?
输入格式:
第一行输入一个整数 nnn。
第二行输入 nnn 个整数,第 iii 个整数是 aia_iai。
输出格式:
输出一个整数,表示结束时得到序列的个数,对 998244353998244353998244353 取模。
数据范围:
对于所有数据,1≤n≤105,1≤ai≤1091\le n\le 10^5,1\le a_i\le 10^91≤n≤105,1≤ai≤109。
题目描述
你有一个序列 aaa 和两种操作:
-
选择 ai<ai+1a_i<a_{i+1}ai<ai+1 并删去 ai+1a_{i+1}ai+1。
-
选择 ai<ai+1a_i<a_{i+1}ai<ai+1 并交换这两个数。
你要不断进行这两种操作,直到无法继续,求结束时会得到多少种本质不同的序列?
题目分析
- 所有的最终序列一定是降序的序列。
- 不同序列的本质区别相当于是在唯一的长度不变的降序序列中删去一些数。
- 所有比前缀最小值大的数都有办法被删去。
这里重要的观察就基本完成了,这时我们会想到使用组合数学 Cn0+Cn1+Cn2+⋯+Cnn=2nC_n^0+C_n^1+C_n^2+\dots+C_n^n=2^nCn0+Cn1+Cn2+⋯+Cnn=2n 来求解,其中 nnn 为能被删去的数的个数。
但是!
如序列 [1,2,2,3][1,2,2,3][1,2,2,3] 如果使用 2n2^n2n 计算结果是 888,然而正确答案是 666,这是因为 [3,21,1][3,2_1,1][3,21,1] 和序列 [3,22,1][3,2_2,1][3,22,1] 是一样的。
所以我们应使用乘法原理,每个数 ai,i∈[1,m]a_i,i\in[1,m]ai,i∈[1,m] 能被删除的数有 kik_iki 个,则每个 aia_iai 可以删除 0∼ki0\sim k_i0∼ki 个,则总数为 ∏i=1m(ki+1)\prod_{i=1}^{m} (k_i+1)∏i=1m(ki+1)。
AC Code
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
map<int,int>mp;
int main()
{int n,x,minn=2e9;scanf("%d",&n);for (int i=0;i<n;i++){scanf("%d",&x);if (!i) minn=min(minn,x);else{if (minn<x) mp[x]++;minn=min(minn,x);}}int ans=1;for (auto it:mp)ans=(long long)ans*(it.second+1)%mod;printf("%d",ans);return 0;
}
End
感谢观看,如有问题欢迎指出。
更新日志
- 2025/10/15 开始书写本篇 CSDN 博客,并完稿发布。