【SSL 2403】图床(三分)

图床

题目链接:SSL 2403

题目大意

有 n 个物品,进行 m 次操作每次会随机选一个展示。
然后给你 n 个范围,要你猜测这个 n 的值。

思路

首先根据于假设一个 n 然后求实际可能的 n 值其实不行,因为你 n 可能很多。
不妨直接考虑一个 n 是的概率。

那全部的展示可能是 nm
考虑对应上它给你的展示。
注意到你无法直接判断 n 的原因是可能有一些从来没有展示过。
那你考虑 n 个物品最后展示了 k 个的概率,或者这里我们求方案除总数就是概率。

那考虑怎么算,首先我们选 k 个物品展示,那展示有展示的顺序(这里是第一次出现的顺序)。
那考虑先放下这些第一次出现的,然后考虑放别的。
那你放在第一次出现中第 i 个后面就有 i 中物品可以选,那按顺序放的话就接在直接后面或者你放过的后面都可以是一样的。
那总共就是 1+2+...+k 中地方*对应选法,那就是 k(k+1)/2 个方案每个数。
那总方案数就是 (nk)k!(k(k+1)/2)mk=n!(nk)!(k(k+1)2)mk

那概率就是:
n!(nk)!nm(k(k+1)2)mk

那我们要找的就是概率最大的那个。
那可以做到 O(T(nmaxnmin)),不过注意到很多东西都很大,不过只有乘法和除法,而且对精度的要求不高,可以把全部都转成指数加减,直接比较指数大小。

然后考虑到概率是数值,肯定是有偏序关系的,那考虑比较两个 n1,n2 的过程,假设 n1 没有 n2 优。
n1!(n1k)!n1m(k(k+1)2)mk<n2!(n2k)!n2m(k(k+1)2)mk
那注意到右边这一坨跟 n 压根没关系,可以直接不管。
n1!(n1k)!n1m<n2!(n2k)!n2m
n1!(n2k)!n2m<n2!(n1k)!n1m

那也就是我们只需要找到 n!(nk)!nm 的最大值。
通过(猜结论 / 搞图像找规律 / 奇怪的数学证明),发现答案的这个东西是单峰的(当 k 的时候)。(不想证了搞数学式子搞麻了)
然后三分即可。

代码

#include<cmath> #include<cstdio> #include<iostream> #include<algorithm> #define ll long long #define ull unsigned long long using namespace std; const int Size=1<<23,NN=1e5+5,M=65535; char buf[Size],*p1=buf,*p2=buf; #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,Size,stdin),p1==p2)?EOF:*p1++) int re; char c; int read() { re = 0; c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') { re = (re << 3) + (re << 1) + c - '0'; c = getchar(); } return re; } void readd() { c = getchar(); while (c < '0' || c > '9') c = getchar(); while (c >= '0' && c <= '9') c = getchar(); if (c == '.') { c = getchar(); while (c >= '0' && c <= '9') c = getchar(); } } const int P = 1e5 + 1000; int nmin, nmax, m, cnt; ull a[P]; double jc[P], log2_[P]; bool f(int x, int y) { return jc[x] + jc[y - cnt] + log2_[y] * m < jc[y] + jc[x - cnt] + log2_[x] * m; } int main() { freopen("pic.in", "r", stdin); freopen("pic.out", "w", stdout); for (int i = 1; i < P; i++) { log2_[i] = log10(i) / log10(2); jc[i] = jc[i - 1] + log2_[i]; } int T = read(); readd(); readd(); readd(); readd(); nmin = read(); nmax = read(); m = read(); while (T--) { for (int i = 1; i <= m; i++) { c = getchar(); while (c < 'a' || c > 'z') c = getchar(); ull now = 0; while (c >= 'a' && c <= 'z') { now = now * 26 + c - 'a'; c = getchar(); } a[i] = now; } sort(a + 1, a + m + 1); cnt = 1; for (int i = 2; i <= m; i++) if (a[i] != a[i - 1]) cnt++; int L = max(cnt, nmin), R = nmax; while (R - L + 1 >= 2) { int mid = (L + R) >> 1; if (f(mid, mid + 1)) L = mid + 1; else R = mid; } int re = L; for (int i = L; i < R; i++) if (f(re, i + 1)) re = i + 1; printf("%d\n", re); } return 0; }

__EOF__

本文作者あおいSakura
本文链接https://www.cnblogs.com/Sakura-TJH/p/SSL_2403.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   あおいSakura  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
历史上的今天:
2022-03-31 【luogu P5903】【模板】树上 k 级祖先(长链剖分)
2022-03-31 Stardust的矩阵(分治)
2022-03-31 【ZOJ 1654】Place the Robots(网络流)
点击右上角即可分享
微信分享提示