Codeforces 1312 D. Count the Arrays (组合数学)

E. Array Shrinking
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
You are given an array a1,a2,…,an. You can perform the following operation any number of times:

Choose a pair of two neighboring equal elements ai=ai+1 (if there is at least one such pair).
Replace them by one element with value ai+1.
After each such operation, the length of the array will decrease by one (and elements are renumerated accordingly). What is the minimum possible length of the array a you can get?

Input
The first line contains the single integer n (1≤n≤500) — the initial length of the array a.

The second line contains n integers a1,a2,…,an (1≤ai≤1000) — the initial array a.

Output
Print the only integer — the minimum possible length you can get after performing the operation described above any number of times.

Examples
inputCopy
5
4 3 2 2 3
outputCopy
2
inputCopy
7
3 3 4 4 4 3 3
outputCopy
2
inputCopy
3
1 3 5
outputCopy
3
inputCopy
1
1000
outputCopy
1
Note
In the first test, this is one of the optimal sequences of operations: 4 3 2 2 3 → 4 3 3 3 → 4 4 3 → 5 3.

In the second test, this is one of the optimal sequences of operations: 3 3 4 4 4 3 3 → 4 4 4 4 3 3 → 4 4 4 4 4 → 5 4 4 4 → 5 5 4 → 6 4.

In the third and fourth tests, you can’t perform the operation at all.

1. 很明显是一道组合数学。
2. 首先在m里面挑出n-1个数就是Cm取n-1。
3. 然后是保证最大的那个元素不在两边，剩下的n-2个元素有n-3个不同元素可以放在最大的元素的左边或者右边，所以是（n-2） * qpow(2,n-3) 。
4. 因为这里n的范围是大于等于2的，而快速幂无法处理负幂，所以这里可以采用特判n=2或者用逆元处理，见代码处。
5. 还有就是快速幂不能带快速乘，具体原因不知，比赛时因快速乘超时了一发，重写快速幂才过。
6. 如果有什么讲的不清楚的地方欢迎提出来，欢迎交流~

``````#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define mod 998244353
#define PI acos(-1)
#define fi first
#define se second
#define lowbit(x) (x&(-x))
#define mp make_pair
#define pb push_back
#define ins insert
#define si size()
#define E exp(1.0)
#define fixed cout.setf(ios::fixed)
#define fixeds(x) setprecision(x)
#pragma GCC optimize(2)
using namespace std;
while(ch<'0'||ch>'9'){if(ch=='-')w=-1;ch=getchar();}
while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
return s*w;}void put1(){ puts("YES") ;}void put2(){ puts("NO") ;}
void put3(){ puts("-1"); }//��=acos(L/2R);
//void debug1(){ cout<<"I CAN AC"<<endl;}//void debug2(){printf("T A T\n");}
ll qp(ll a,ll b, ll p){ll ans = 1;while(b){if(b&1){
ans = (ans*a)%p;--b;}a = (a*a)%p;b >>= 1;}return ans%p;}
const int manx=1e3+5;

ll Inv(ll x){
return qp(x,mod-2,mod);
}
ll Cal(ll n,ll m){
if (m>n) return 0;
ll ans = 1;
for (int i = 1; i <= m; ++i) ans=ans*Inv(i)%mod*(n-i+1)%mod;
return ans%mod;
}
int main()
{
ll ans=Cal(m,n-1);
ans%=mod;
/*特判
if(n>2) ans=ans*qp(2,n-3,mod)%mod*(n-2)%mod;
else ans=0;
*/
//逆元
ans=ans*qp(2,n-2,mod)%mod*(n-2)%mod*Inv(2);
ans=(ans+mod)%mod;
printf("%lld\n",ans);
return 0;
}
``````