#565. 「LibreOJ Round #10」mathematican 的二进制(期望 + 分治NTT)
题面
戳这里,题意简单易懂。
题解
首先我们发现,操作是可以不考虑顺序的,因为每次操作会加一个 \(1\) ,每次进位会减少一个 \(1\) ,我们就可以考虑最后 \(1\) 的个数(也就是最后的和),以及成功操作次数,就行了。
然后根据期望的线性性,我们可以从低到高按位考虑贡献。
考虑一个递推:\(f(i, j)\) 表示从后往前第 \(i\) 位总共被改变 \(j\) 次的概率,那么有两种转移:
- 进位:\(\displaystyle f(i - 1, j) \to f(i, \lfloor \frac j 2 \rfloor)\)
- 操作:对于第 \(i\) 位每个概率为 \(p\) 的操作, \(f(i, j - 1)p + f(i, j)(1 - p) \to f(i, j)\)
注意要先转移第一个,再转移第二个,因为第二个可以对于第一个操作上来的数位进行贡献。
然后这样直接实现就是 \(O(m^2)\) 的,但是我们可以考虑优化,对于第二个容易观察就是乘上了 \(P(x) = \prod_i p_ix + (1-p_i)\) 这个生成函数。
显然这个我们可以利用 分治 \(NTT\) 来解决。
进位的话我们可以暴力进位,因为每个操作对于 分治 \(NTT\) 的贡献可以放缩成一个等比级数:\(\displaystyle \sum_{i = 0} ^ {\infty} 2^{-i} = 2\) 。
所以最后时间复杂度就是 \(O(m \log^2 m)\) 的。
总结
对于一些期望题,可以考虑期望的线性性,以及试试操作顺序是否不影响答案。
然后考虑 \(NTT\) 优化概率生成函数就行啦。
代码
#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 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 DEBUG(...) fprintf(stderr, __VA_ARGS__)
#define pb push_backusing namespace std;typedef long long ll;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_shadowfreopen ("565.in", "r", stdin);freopen ("565.out", "w", stdout);
#endif
}const int N = 200100, Mod = 998244353;ll fpm(ll x, int power) {ll res = 1;for (; power; power >>= 1, (x *= x) %= Mod)if (power & 1) (res *= x) %= Mod;return res;
}inline int Add(int a, int b) { return (a += b) >= Mod ? a - Mod : a; }template<int Maxn>
struct Number_Theoretic_Transfrom {const int g = 3;ll powg[Maxn + 5], invpowg[Maxn + 5]; int rev[Maxn + 5];void NTT_Init() {for (int i = 2; i <= Maxn; i <<= 1)invpowg[i] = fpm((powg[i] = fpm(g, (Mod - 1) / i)), Mod - 2);}int len;void NTT(ll P[], int opt) {For (i, 0, len - 1) if (i < rev[i]) swap(P[i], P[rev[i]]);for (int i = 2, p = 1; i <= len; p = i, i <<= 1) {ll Wi = opt == 1 ? powg[i] : invpowg[i];for (int j = 0; j < len; j += i) {ll x = 1;For (k, 0, p - 1) {ll u = P[j + k], v = P[j + k + p] * x % Mod;P[j + k] = Add(u, v);P[j + k + p] = Add(u, Mod - v);(x *= Wi) %= Mod;}}}if (!~opt) {ll invn = fpm(len, Mod - 2);For (i, 0, len - 1) (P[i] *= invn) %= Mod;}}ll A[Maxn + 5], B[Maxn + 5];void Mult(int *a, int *b, int *c, int lena, int lenb) {int cnt = 0;for (len = 1; len <= lena + lenb; len <<= 1) ++ cnt;For (i, 0, len - 1) rev[i] = (rev[i >> 1] >> 1) | ((i & 1) << (cnt - 1));For (i, 0, len - 1)A[i] = i <= lena ? a[i] : 0, B[i] = i <= lenb ? b[i] : 0;NTT(A, 1); NTT(B, 1); For (i, 0, len - 1) (A[i] *= B[i]) %= Mod; NTT(A, -1);For (i, 0, lena + lenb) c[i] = A[i];}};Number_Theoretic_Transfrom<1 << 20> NTT;int n, m;int pool[N << 5], *ptr = pool;struct Poly {int *a, len;Poly(int l) { a = ptr; ptr += (len = l) + 1; }void Out() {debug(len);For (i, 1, n) printf ("%d%c", a[i], i == iend ? '\n' : ' ');}};inline bool operator < (const Poly &lhs, const Poly &rhs) {return lhs.len > rhs.len;
}vector<int> Base[N];Poly I(0);
Poly Calc(int id) {if (!(bool)Base[id].size()) return I;priority_queue<Poly> P;for (int prob : Base[id]) {Poly cur(1);cur.a[1] = prob;cur.a[0] = Mod + 1 - prob;P.push(cur);}while (P.size() > 1) {Poly a = P.top(); P.pop();Poly b = P.top(); P.pop();Poly c(a.len + b.len);NTT.Mult(a.a, b.a, c.a, a.len, b.len);P.push(c);}return P.top();
}int main () {File();NTT.NTT_Init();n = read(); m = read();For (i, 1, m) {int pos = read(), x = read(), y = read();Base[pos].pb(1ll * x * fpm(y, Mod - 2) % Mod);}ll ans = 0;Poly res(0); res.a[0] = 1;For (i, 0, n + 20) {Poly tmp = Calc(i);if (tmp.len) {NTT.Mult(res.a, tmp.a, res.a, res.len, tmp.len);res.len = res.len + tmp.len;}For (j, 0, res.len) {ans = (ans + 1ll * res.a[j] * j) % Mod;int temp = res.a[j]; res.a[j] = 0;(res.a[j >> 1] += temp) %= Mod;}res.len >>= 1;}printf ("%lld\n", ans);return 0;}
转载于:https://www.cnblogs.com/zjp-shadow/p/9709010.html
#565. 「LibreOJ Round #10」mathematican 的二进制(期望 + 分治NTT)相关推荐
- 「LibreOJ Round #11」Misaka Network 与求和(杜教筛 + Min_25)
#572. 「LibreOJ Round #11」Misaka Network 与求和 推式子 ∑i=1n∑j=1nf(gcd(i,j))k∑d=1nf(d)k∑i=1nd∑j=1nd[gcd(i,j ...
- LibreOJ545. 「LibreOJ β Round #7」小埋与游乐场【网络流】
545. 「LibreOJ β Round #7」小埋与游乐场 [题目描述] 传送门 [题解] 网络流,我们发现lowbit之后相同的点连出的边是相同的,所以可以缩点. [代码如下] #include ...
- [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机)
[LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机) 试题描述 IOI 的比赛开始了.Jsp 和 Rlc 坐在一个角落,这时他们听到了一个异样的声音 -- 接着他们发现自己收 ...
- #530. 「LibreOJ β Round #5」最小倍数 二分 + 数论
传送门 文章目录 题意: 思路: 题意: 思路: 本来想刷数位dpdpdp,无意间碰到了这个题来水水. 我们知道n!n!n!中质因子ppp的个数为∑i=1npi\sum_{i=1} \frac{n}{ ...
- [LOJ #521]「LibreOJ β Round #3」绯色 IOI(抵达)(结论)
#521. 「LibreOJ β Round #3」绯色 IOI(抵达) description solution 因为点的庇护所不能为自身,题目背景在树上,有结论一定是两个相邻点互为庇护所 所以树一 ...
- loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分...
$ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinob ...
- 「LibreOJ β Round #4」子集
https://loj.ac/problem/526 题目描述 qmqmqm有一个长为 n 的数列 a1,a2,--,an,你需要选择集合{1,2,--,n}的一个子集,使得这个子集中任意两个元素 i ...
- LOJ #516. 「LibreOJ β Round #2」DP 一般看规律
题目描述 给定一个长度为 n 的序列 a,一共有 m 个操作. 每次操作的内容为:给定 x,y,序列中所有 x 会变成 y. 同时我们有一份代码: int ans = 2147483647; for ...
- 「LibreOJ Round #6」花火
转化思维的好题! 链接:here 大致题意: 有$ n$个数字,你每次可以交换相邻两个,还有一次交换任意两个元素的机会,求最少的交换次数使得这些数字升序排序(原数列两两不同) $ solotion:$ ...
- 「LibreOJ Round #11」Misaka Network 与测试 (网络流跑二分图匹配)
description 研究者们想要测试 Misaka Network,于是他们把 Misaka Network 中的所有妹妹们召集到了一起. 现在妹妹们排成了 N行 M 列,有的位置没有人.现在研究 ...
最新文章
- Linux服务器生产环境中的文件删除与替换
- php 正则匹配字母和数字,正则匹配密码只能是数字和字母组合字符串功能【php与js实现】...
- python为类定义构造函数
- eof函数怎么用matlab,EOF的源程序MATLAB.doc
- C++ 任意类型 转 string
- Delphi XE3 下载
- iPhone中使用ShareKit一键分享到Facebook,Twitter等多平台
- PS长投影文字制作教程
- 抖音账号如何打造,抖音直播带货怎么做:国仁楠哥
- 商业智能,数据仓库,ETL,数仓调度工具informatica介绍手账(三)
- Facebook主页照片和封面照片的尺寸要求
- 如何给导师发邮件?【附带邮件模板】
- Github 上火热的十个 Python 项目,从Debug工具到AI水军、量化交易系统。( 嗨学编程)
- 【mba项目管理论文】S 公司项目管理绩效评价现状与问题(节选)
- IDEA向前向后箭头,左右箭头如何设置
- mac php pear,OSX EI Captain中安装Pear等三方软件不成功的解决方法
- itextpdf 添加折线图、饼图、柱状图
- 苹果商店ASA广告投放之TTR和CR
- 【Git】Git获取Commit修改文件列表
- 在微软从测试开发工程师到主管
热门文章
- Lambda 表达式入门,这篇够了!
- 我的天!你竟然没有在SpringBoot中使用过异步请求和异步调用...
- c#调用python脚本效率,C#调用Python脚本 C#调用Python脚本的简单示例
- 24 内置函数 命名元组(namedtuple) ,os ,sys,序列化,pickle,json
- javascript 编程指南
- C语言 文件操作5--文件的常用函数
- 学习是一件高尚而孤独的事情
- VS2010制作dll
- iOS应用审核的通关秘籍
- Android开发工程师,前行路上的14项技能