计数组合数价值序列
Posted 行码棋
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了计数组合数价值序列相关的知识,希望对你有一定的参考价值。
题目链接:
https://ac.nowcoder.com/acm/contest/23481/B
本题不要计算序列a的价值,因为从这个方面考虑很难做出来。
应该从取序列中的哪些值才能使序列a的价值不变来考虑。
对于三个数来讨论:
-
a
i
<
a
j
<
a
k
a_i < a_j <a_k
ai<aj<ak或
a
i
>
a
j
>
a
k
a_i >a_j>a_k
ai>aj>ak时
删除中间的数,序列的价值不会变化。如果中间相同的数有k
个,情况数为 2 k 2^k 2k -
a
i
<
a
j
>
a
k
a_i < a_j >a_k
ai<aj>ak或
a
i
>
a
j
<
a
k
a_i >a_j<a_k
ai>aj<ak时
删除中间的值,序列价值会发生变化,所以不能删除。但是如果中间的值有多个相等的话,要至少留一个值即可。如果相等数的个数为k
,则情况数为 2 k − 1 2^k-1 2k−1(去除为空的情况)
接下来,就是对中间的相同的数进行讨论了
把相等的数看成一个连通块,设为 [ i , j ] [i,j] [i,j]
- 如果满足 a i − 1 < a i = . . . = a j < a j + 1 a_i-1<a_i=...=a_j<a_j+1 ai−1<ai=...=aj<aj+1 或 a i − 1 > a i = . . . = a j > a j + 1 a_i-1>a_i=...=a_j>a_j+1 ai−1>ai=...=aj>aj+1(且要满足 i > 1 , j < n i>1,j<n i>1,j<n),则区间 [ i , j ] [i,j] [i,j]的数可以全部删除,不影响价值,这样的区间对答案贡献有 2 j − i + 1 2^j-i+1 2j−i+1种方案。
- 否则区间 [ i , j ] [i,j] [i,j]的数必须保留一个,这样的区间对答案贡献 2 j − i + 1 − 1 2^j-i+1-1 2j−i+1−1 种方案。把所有区间的贡献连乘起来就是答案。
#include<bits/stdc++.h>
using namespace std;
using ll = long long;
const int N = 1e5 + 5, mod = 998244353;
vector<ll> fac(N);
void solve()
int n;
cin >> n;
vector<int> a(n);
for(auto &i : a) cin >> i;
ll res = 1;
for(int i = 0, j = 0; i < n; i++)
j = i;
while(j < n - 1 && a[j + 1] == a[i]) j++;
if(i - 1 >= 0 and j + 1 < n and (a[i - 1] < a[i] && a[i] < a[j + 1] || a[i - 1] > a[i] && a[i] > a[j + 1]))
res = res * fac[j - i + 1] % mod;
else res = res * (fac[j - i + 1] - 1) % mod;
i = j;
cout << res << "\\n";
int main()
ios::sync_with_stdio(false);
cin.tie(nullptr);
fac[0] = 1;
for(int i = 1; i < N; i++)
fac[i] = fac[i - 1] * 2 % mod;
int t;
cin >> t;
// t = 1;
while(t--) solve();
return 0;
以上是关于计数组合数价值序列的主要内容,如果未能解决你的问题,请参考以下文章