【组合数学题目】宇宙分解
算法竞赛:组合数学、组合、乘法原理
题目链接:洛谷 P13550 宇宙分解
题目描述:
你有一个序列 a a a 和两种操作:
- 选择 a i < a i + 1 a_i<a_{i+1} ai<ai+1 并删去 a i + 1 a_{i+1} ai+1。
- 选择 a i < a i + 1 a_i<a_{i+1} ai<ai+1 并交换这两个数。
你要不断进行这两种操作,直到无法继续,求结束时会得到多少种本质不同的序列?
输入格式:
第一行输入一个整数 n n n。
第二行输入 n n n 个整数,第 i i i 个整数是 a i a_i ai。
输出格式:
输出一个整数,表示结束时得到序列的个数,对 998244353 998244353 998244353 取模。
数据范围:
对于所有数据, 1 ≤ n ≤ 1 0 5 , 1 ≤ a i ≤ 1 0 9 1\le n\le 10^5,1\le a_i\le 10^9 1≤n≤105,1≤ai≤109。
题目描述
你有一个序列 a a a 和两种操作:
-
选择 a i < a i + 1 a_i<a_{i+1} ai<ai+1 并删去 a i + 1 a_{i+1} ai+1。
-
选择 a i < a i + 1 a_i<a_{i+1} ai<ai+1 并交换这两个数。
你要不断进行这两种操作,直到无法继续,求结束时会得到多少种本质不同的序列?
题目分析
- 所有的最终序列一定是降序的序列。
- 不同序列的本质区别相当于是在唯一的长度不变的降序序列中删去一些数。
- 所有比前缀最小值大的数都有办法被删去。
这里重要的观察就基本完成了,这时我们会想到使用组合数学 C n 0 + C n 1 + C n 2 + ⋯ + C n n = 2 n C_n^0+C_n^1+C_n^2+\dots+C_n^n=2^n Cn0+Cn1+Cn2+⋯+Cnn=2n 来求解,其中 n n n 为能被删去的数的个数。
但是!
如序列 [ 1 , 2 , 2 , 3 ] [1,2,2,3] [1,2,2,3] 如果使用 2 n 2^n 2n 计算结果是 8 8 8,然而正确答案是 6 6 6,这是因为 [ 3 , 2 1 , 1 ] [3,2_1,1] [3,21,1] 和序列 [ 3 , 2 2 , 1 ] [3,2_2,1] [3,22,1] 是一样的。
所以我们应使用乘法原理,每个数 a i , i ∈ [ 1 , m ] a_i,i\in[1,m] ai,i∈[1,m] 能被删除的数有 k i k_i ki 个,则每个 a i a_i ai 可以删除 0 ∼ k i 0\sim k_i 0∼ki 个,则总数为 ∏ i = 1 m ( k i + 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 开始书写本篇 优快云 博客,并完稿发布。
本篇博客最早由本人发布于洛谷文章广场,本篇博客对其进行了修改调整与完善丰富。

8697

被折叠的 条评论
为什么被折叠?



