CF1153F Serval and Bonus Problem

CF1153F Serval and Bonus Problem

官方的解法是O(n2)O(n2)的,这里给出一个O(nlogn)O(nlogn)的做法。

首先对于长度为ll的线段,显然它的答案就是长度为11的线段的答案×l×l,这样做只是为了方便计算。

考虑对于数轴上区间[0,1][0,1]内任意一个点xx,它被一条随机线段覆盖的概率是多少:线段的两个端点都在它左边的概率是x2x2、都在它右边的概率是(1x)2(1x)2,那么它被覆盖的概率即为p(x)=1x2(1x)2=2x(1x)p(x)=1x2(1x)2=2x(1x)

那么他被kk条线段覆盖的概率为f(x)=ni=k(ni)p(x)i(1p(x))nif(x)=ni=k(ni)p(x)i(1p(x))ni

根据定积分的定义就得到区间[0,1][0,1]内被kk条线段覆盖的长度期望为10f(x)dx10f(x)dx

现在我们的问题就是怎么算这个东西了:

10f(x)dx=10ni=k(ni)(2x(1x))i(12x(1x))nidx=ni=k(ni)10(2x(1x))inij=0(nij)(2x(1x))jdx=ni=k(ni)nij=0(nij)(1)j2(i+j)10xi+j(1x)i+jdx

推到这里,就可以把积分去掉了,这是一个Beta Function的形式:记结论吧

B(x,y)=10tx1(1t)y1dt=(x1)!(y1)!(x+y1)!

代入得:

10f(x)dx=ni=k(ni)nij=0(nij)(1)j2(i+j)((i+j)!)2(2(i+j)+1)!=n!ni=knij=01i!(1)jj!2i+j((i+j)!)2(2(i+j)+1)!(n(i+j))!

t=i+jf[i]=1ig[j]=(1)jj!h[t]=2t(t!)2(2t+1)!(nt)!,考虑枚举t

10f(x)dx=n!nt=kh[t]ti=kf[i]g[ti]

这后面就是一个非常显然的卷积式子了,直接FFT即可。

答案记得×l

Copy
//written by newbiechd #include <cstdio> #include <cctype> #include <algorithm> #define BUF 1000000 using namespace std; const int N = 100003, yyb = 998244353, Gg = 3, Gi = 332748118; char buf[BUF], *p1, *p2; inline char gc() { return p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, BUF, stdin), p1 == p2) ? EOF : *p1++; } inline int rd() { register int f = 0; register char c; while (!isdigit(c = gc())) {} do f = f * 10 + (c ^ 48); while (isdigit(c = gc())); return f; } int rev[N], G[2][N]; inline int power(int x, int y) { register int o = 1; for (; y; y >>= 1, x = 1ll * x * x % yyb) if (y & 1) o = 1ll * o * x % yyb; return o; } inline void ntt(int *f, int len, int opt) { register int i, j, k, x, y, p, q; for (i = 1; i < len; ++i) if (i < rev[i]) swap(f[i], f[rev[i]]); for (i = 1; i < len; i <<= 1) { p = G[opt][i]; for (j = 0; j < len; j += i << 1) for (k = 0, q = 1; k < i; ++k, q = 1ll * p * q % yyb) x = f[j | k], y = 1ll * q * f[i | j | k] % yyb, f[j | k] = (x + y) % yyb, f[i | j | k] = (x - y) % yyb; } } int fac[N], invFac[N], f[N], g[N], h[N]; int main() { #ifndef ONLINE_JUDGE freopen("a.in", "r", stdin); freopen("a.out", "w", stdout); #endif int n = rd(), m = n << 1 | 1, k = rd(), l = rd(), i, len, tmp, ans = 0; fac[0] = 1; for (i = 1; i <= m; ++i) fac[i] = 1ll * fac[i - 1] * i % yyb; invFac[m] = power(fac[m], yyb - 2); for (i = m; i; --i) invFac[i - 1] = 1ll * invFac[i] * i % yyb; for (i = k; i <= n; ++i) f[i] = invFac[i]; for (i = 0; i <= n; ++i) g[i] = i & 1 ? yyb - invFac[i] : invFac[i]; for (len = 1; len <= m; len <<= 1) {} for (i = 1; i < len; ++i) rev[i] = (rev[i >> 1] >> 1) | (i & 1 ? len >> 1 : 0); for (i = 1; i < len; i <<= 1) G[0][i] = power(Gg, (yyb - 1) / (i << 1)), G[1][i] = power(Gi, (yyb - 1) / (i << 1)); ntt(f, len, 0), ntt(g, len, 0); for (i = 0; i < len; ++i) f[i] = 1ll * f[i] * g[i] % yyb; ntt(f, len, 1), tmp = power(len, yyb - 2); for (i = 1; i <= n; ++i) f[i] = 1ll * f[i] * tmp % yyb; for (i = 1, tmp = 2; i <= n; tmp = (tmp << 1) % yyb, ++i) h[i] = 1ll * fac[i] * fac[i] % yyb * tmp % yyb * invFac[i << 1 | 1] % yyb * invFac[n - i] % yyb; for (i = k; i <= n; ++i) ans = (1ll * f[i] * h[i] % yyb + ans) % yyb; ans = 1ll * ans * fac[n] % yyb * l % yyb, printf("%d\n", (ans + yyb) % yyb); return 0; }
posted @   newbiechd  阅读(718)  评论(8编辑  收藏  举报
编辑推荐:
· Linux glibc自带哈希表的用例及性能测试
· 深入理解 Mybatis 分库分表执行原理
· 如何打造一个高并发系统?
· .NET Core GC压缩(compact_phase)底层原理浅谈
· 现代计算机视觉入门之:什么是图片特征编码
阅读排行:
· 手把手教你在本地部署DeepSeek R1,搭建web-ui ,建议收藏!
· Spring AI + Ollama 实现 deepseek-r1 的API服务和调用
· 数据库服务器 SQL Server 版本升级公告
· 程序员常用高效实用工具推荐,办公效率提升利器!
· C#/.NET/.NET Core技术前沿周刊 | 第 23 期(2025年1.20-1.26)
点击右上角即可分享
微信分享提示