题意
有一个长度为 n 的整数列 a1,a2,⋯,an ,每个元素在 [1,x] 中的整数中均匀随机生成。
- 有 q 个询问,第 i 个询问的结果是下标在 [li,ri] 的元素的最小值。
- 求这 q 个询问结果的最大值的期望,mod666623333 。
数据范围
1≤n,q,x≤2000 。
题解
参考了 fjzzq2002 的题解。
有个很有用的结论。
对于非负实数变量 X 我们有:
E(X)=∫∞0P(X≥x)dx
对于 X 是离散的非负整数变量的情况,我们有:
E(X)=∞∑x=1P(X≥x)
如何理解呢?我们可以考虑期望的定义式 E(X)=∑xP(X=x)x 其实是一个数面积的过程,也就是积分。
然后等式两边的其实就是数面积的两种过程,一个是竖着数,另外一个是横着数。
推广一下其实如果是求 E(f(X)) 我们考虑求导后积分也就是:
E(f(x))=∫∞0f′(x)P(X≥x)dx
我们套用这个后就有
E(ans)=∞∑i=1P(ans≥i)=x−1∑i=0(1−P(ans≤i))
这样就好做多了,考虑枚举 i ,然后算 P(ans≤i) 也就是,每个区间的 min 都 ≤i 的概率,假设这个 i=t 。
我们发现如果一个区间包含另外一个区间的话,那么它的最小值一定不会比小区间大,所以一定不会贡献到答案,那么我们可以去掉大区间。转化后,所有区间就是互不包含的了。
考虑记 fi 为右端点不超过 i 的区间询问结果都 ≤t 的概率。
如果不存在一个 r=i ,那么就是 fi=fi−1 。
否则记右端点为 i 的区间左端点为 j ,枚举区间内最后一个 ≤t 的数的位置 l ,那么我们有
fi=i∑l=jfl−1tx(1−tx)i−l
然后发现是 O(xn2) 的,发现它能跑过QAQ
显然我们可以使它更加正确,推导一下式子就有(注意有 t<x )
fi=tx(1−tx)ii∑l=jfl−1(1−tx)−l
然后我们就可以用前缀和优化到 O(xn) 。
其实还可以继续优化。。
观察转移方程发现答案其实是一个关于 tx 的 O(n) 次多项式,也就是关于 i 的 O(n) 次多项式。
所以它的前缀和仍然是一个 O(n) 次多项式,我们算出前 O(n) 项和前缀和,插值出 x 处的前缀和即可。复杂度就优化成 O(n2) 啦。
代码
#include <bits/stdc++.h>
#define For(i, l, r) for (register int i = (l), i##end = (int)(r); i <= i##end; ++i)
#define Fordown(i, r, l) for (register int i = (r), i##end = (int)(l); i >= i##end; --i)
#define Rep(i, r) for (register int i = (0), i##end = (int)(r); i < i##end; ++i)
#define Set(a, v) memset(a, v, sizeof(a))
#define Cpy(a, b) memcpy(a, b, sizeof(a))
#define debug(x) cout << #x << ": " << (x) << endl
#define l first
#define r second
using namespace std;
typedef pair<int, int> PII;
template<typename T> inline bool chkmin(T &a, T b) { return b < a ? a = b, 1 : 0; }
template<typename T> inline bool chkmax(T &a, T b) { return b > a ? a = b, 1 : 0; }
inline int read() {
int x(0), sgn(1); char ch(getchar());
for (; !isdigit(ch); ch = getchar()) if (ch == '-') sgn = -1;
for (; isdigit(ch); ch = getchar()) x = (x * 10) + (ch ^ 48);
return x * sgn;
}
void File() {
#ifdef zjp_shadow
freopen ("P3600.in", "r", stdin);
freopen ("P3600.out", "w", stdout);
#endif
}
const int N = 2e3 + 1e2, Mod = 666623333;
inline int fpm(int x, int power) {
int res = 1;
for (; power; power >>= 1, x = 1ll * x * x % Mod)
if (power & 1) res = 1ll * res * x % Mod;
return res;
}
int n, x, q, len, f[N]; PII S[N];
int V[N], powb[N], invpowb[N], sum[N];
int main () {
File();
n = read(); x = read(); q = read();
For (i, 1, q)
S[i].l = read(), S[i].r = read();
sort(S + 1, S + q + 1);
For (i, 1, q) {
bool flag = true;
For (j, i + 1, q)
if (S[i].l <= S[j].l && S[j].r <= S[i].r) flag = false;
if (flag)
V[S[i].r] = S[i].l;
}
int ans = 0, invx = fpm(x, Mod - 2);
Rep (v, x) {
f[0] = powb[0] = invpowb[0] = 1;
int coef = 1ll * v * invx % Mod;
powb[1] = (Mod + 1 - coef) % Mod;
invpowb[1] = fpm(powb[1], Mod - 2);
For (i, 2, n) {
powb[i] = 1ll * powb[i - 1] * powb[1] % Mod;
invpowb[i] = 1ll * invpowb[i - 1] * invpowb[1] % Mod;
}
For (i, 1, n) {
sum[i] = (sum[i - 1] + 1ll * f[i - 1] * invpowb[i]) % Mod;
if (!V[i]) f[i] = f[i - 1];
else f[i] = 1ll * (Mod + sum[i] - sum[V[i] - 1]) * coef % Mod * powb[i] % Mod;
}
(ans += Mod + 1 - f[n]) %= Mod;
}
printf ("%d\n", ans);
return 0;
}
__EOF__
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 地球OL攻略 —— 某应届生求职总结
· 周边上新:园子的第一款马克杯温暖上架
· Open-Sora 2.0 重磅开源!
· 提示词工程——AI应用必不可少的技术
· .NET周刊【3月第1期 2025-03-02】
2018-03-21 BZOJ4008 : [HNOI2015]亚瑟王(期望dp)