- 239's solution
-
P239's Solution
- @ 2026-4-5 10:32:54
对低于某个具体的序列,计算:
- 等于所有前缀的最小值之和
- 等于所有后缀的最小值之和
- 等于序列最小值
则其「自由度」为:
对于一个带有 的序列,设其最小正项为 , 有 个,则其实际最小值不小于 的方案数为:
利用拉格朗日插值快速计算 ,时间复杂度为 ,空间复杂度为 。
#include <bits/stdc++.h>
#define int long long
using namespace std;
const int P = 1e9 + 7;
int divs(int a, int b, int p)
{
if (b % a == 0) return b / a;
int x = divs(p % a, a - b % a, a);
return (x * p + b) / a;
}
int power(int x, int y)
{
if (y == 0) return 1;
if (y == 1) return x;
int c = power(x, y >> 1);
c = c * c % P;
if (y & 1) c = c * x % P;
return c;
}
const int N = 1000, NN = N + 12;
int a[NN], p[NN][NN], q[NN][NN], fc[NN], pd1[NN], pd2[NN];
void init()
{
fc[0] = 1;
for (int i = 1; i <= N + 2; i++)
fc[i] = fc[i - 1] * i % P;
for (int i = 1; i <= N; i++)
for (int j = 1; j <= i + 2; j++)
{
p[i][j] = p[i][j - 1] + power(j, i);
if (p[i][j] >= P) p[i][j] -= P;
q[i][j] = p[i][j] * divs(fc[j - 1] * fc[i + 2 - j] % P, 1, P) % P;
if ((i + 2 - j) & 1) q[i][j] = P - q[i][j];
if (q[i][j] == P) q[i][j] = 0;
}
}
int sum(int x, int y)
{
if (!x) return y;
if (y <= x + 2) return p[x][y];
for (int i = 0; i <= x + 3; i++)
pd1[i] = pd2[i] = 0;
pd1[0] = pd2[x + 3] = 1;
for (int i = 1; i <= x + 2; i++)
pd1[i] = pd1[i - 1] * (y - i) % P;
for (int i = x + 2; i >= 1; i--)
pd2[i] = pd2[i + 1] * (y - i) % P;
int ans = 0;
for (int i = 1; i <= x + 2; i++)
{
ans += pd1[i - 1] * pd2[i + 1] % P * q[x][i] % P;
if (ans >= P) ans -= P;
}
return ans;
}
int sum(int l, int r, int x)
{
int ans = sum(x, r) - sum(x, l - 1);
if (ans < 0) ans += P;
return ans;
}
int solve(int n, int V, int s)
{
int t = 0, w = V, ans = 0;
for (int i = 1; i <= n; i++)
{
if (!a[i]) t++;
if (a[i]) w = min(w, a[i]);
ans += sum(V - w + 1, V, t) * power(V, s - t) % P;
}
return ans % P;
}
signed main()
{
init();
int n, V, s = 0, w = 1e9;
cin >> n >> V;
w = V;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
if (!a[i]) s++;
if (a[i]) w = min(w, a[i]);
}
int ans = n * (power(V, s) - 2 * sum(V - w + 1, V, s) + 2 * P) % P;
ans += solve(n, V, s);
reverse(a + 1, a + n + 1);
ans += solve(n, V, s);
cout << ans % P << endl;
return 0;
}