题目主要是计算组合数。
当遇到0时,我们先统计一共有多少连续的0,cnt个。
然后用提前维护的前缀最小值(除0外),后缀最大值(除0外),我们可以得到这串0的取值范围[maxa_i, mina_i]。
根据组合数学,从 n 个元素中可重复选取 m 个元素的选法数量为组合数 C (n + m - 1, m),其中 C (a, b) 表示从 a 个元素中选 b 个的组合数(计算公式:C (a, b) = a! / (b!・(a-b)! ))。
对答案更新 ans = ans * C (mina_i-maxa_i+1 + cnt - 1, cnt)
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N = 1e6+1100, mod = 1e9+7;
int n;
int a[N], maxa[N], mina[N];
ll fac[N], infac[N];
ll dp[1010];
ll qpow(ll x, ll y)
{
ll ans = 1;
x %= mod; y %= mod;
while (y)
{
if (y&1) ans = ans*x%mod;
y >>= 1;
x = x*x%mod;
}
return ans;
}
ll C(ll x, ll y)
{
return fac[x] *infac[y]%mod *infac[x-y]%mod;
}
int main()
{
fac[0] = 1;
for (ll i=1; i<N; ++i) fac[i] = (fac[i-1]*i)%mod;
infac[N-1] = qpow(fac[N-1], mod-2);
for (ll i=N-2; i>=0; --i) infac[i] = (infac[i+1]*(i+1))%mod;
cin>>n;
mina[0] = 1000;
for (int i=1; i<=n; ++i)
{
cin>>a[i];
if (a[i] != 0)
mina[i] = min(mina[i-1], a[i]);
else
mina[i] = mina[i-1];
}
maxa[n+1] = 1;
for (int i=n; i>=1; --i)
{
maxa[i] = max(maxa[i+1], a[i]);
}
ll ans = 1, cnt = 0;
for (int i=1; i<=n; ++i)
{
if (a[i] == 0) cnt++;
else if (cnt != 0)
{
ans = ans*C(mina[i-1]-maxa[i-1]+1+cnt-1, cnt)%mod;
cnt = 0;
}
}
if (cnt != 0)
{
ans = ans*C(mina[n]-maxa[n]+1+cnt-1, cnt)%mod;
cnt = 0;
}
cout<<ans<<'\n';
return 0;
}



京公网安备 11010502036488号