题面

戳这里,题意简单易懂。

题解

首先我们发现,操作是可以不考虑顺序的,因为每次操作会加一个 \(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)相关推荐

  1. 「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 ...

  2. LibreOJ545. 「LibreOJ β Round #7」小埋与游乐场【网络流】

    545. 「LibreOJ β Round #7」小埋与游乐场 [题目描述] 传送门 [题解] 网络流,我们发现lowbit之后相同的点连出的边是相同的,所以可以缩点. [代码如下] #include ...

  3. [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机)

    [LOJ#522]「LibreOJ β Round #3」绯色 IOI(危机) 试题描述 IOI 的比赛开始了.Jsp 和 Rlc 坐在一个角落,这时他们听到了一个异样的声音 -- 接着他们发现自己收 ...

  4. #530. 「LibreOJ β Round #5」最小倍数 二分 + 数论

    传送门 文章目录 题意: 思路: 题意: 思路: 本来想刷数位dpdpdp,无意间碰到了这个题来水水. 我们知道n!n!n!中质因子ppp的个数为∑i=1npi\sum_{i=1} \frac{n}{ ...

  5. [LOJ #521]「LibreOJ β Round #3」绯色 IOI(抵达)(结论)

    #521. 「LibreOJ β Round #3」绯色 IOI(抵达) description solution 因为点的庇护所不能为自身,题目背景在树上,有结论一定是两个相邻点互为庇护所 所以树一 ...

  6. loj #535. 「LibreOJ Round #6」花火 树状数组求逆序对+主席树二维数点+整体二分...

    $ \color{#0066ff}{ 题目描述 }$ 「Hanabi, hanabi--」 一听说祭典上没有烟火,Karen 一脸沮丧. 「有的哦-- 虽然比不上大型烟花就是了.」 还好 Shinob ...

  7. 「LibreOJ β Round #4」子集

    https://loj.ac/problem/526 题目描述 qmqmqm有一个长为 n 的数列 a1,a2,--,an,你需要选择集合{1,2,--,n}的一个子集,使得这个子集中任意两个元素 i ...

  8. LOJ #516. 「LibreOJ β Round #2」DP 一般看规律

    题目描述 给定一个长度为 n 的序列 a,一共有 m 个操作. 每次操作的内容为:给定 x,y,序列中所有 x 会变成 y. 同时我们有一份代码: int ans = 2147483647; for ...

  9. 「LibreOJ Round #6」花火

    转化思维的好题! 链接:here 大致题意: 有$ n$个数字,你每次可以交换相邻两个,还有一次交换任意两个元素的机会,求最少的交换次数使得这些数字升序排序(原数列两两不同) $ solotion:$ ...

  10. 「LibreOJ Round #11」Misaka Network 与测试 (网络流跑二分图匹配)

    description 研究者们想要测试 Misaka Network,于是他们把 Misaka Network 中的所有妹妹们召集到了一起. 现在妹妹们排成了 N行 M 列,有的位置没有人.现在研究 ...

最新文章

  1. Linux服务器生产环境中的文件删除与替换
  2. php 正则匹配字母和数字,正则匹配密码只能是数字和字母组合字符串功能【php与js实现】...
  3. python为类定义构造函数
  4. eof函数怎么用matlab,EOF的源程序MATLAB.doc
  5. C++ 任意类型 转 string
  6. Delphi XE3 下载
  7. iPhone中使用ShareKit一键分享到Facebook,Twitter等多平台
  8. PS长投影文字制作教程
  9. 抖音账号如何打造,抖音直播带货怎么做:国仁楠哥
  10. 商业智能,数据仓库,ETL,数仓调度工具informatica介绍手账(三)
  11. Facebook主页照片和封面照片的尺寸要求
  12. 如何给导师发邮件?【附带邮件模板】
  13. Github 上火热的十个 Python 项目,从Debug工具到AI水军、量化交易系统。( 嗨学编程)
  14. 【mba项目管理论文】S 公司项目管理绩效评价现状与问题(节选)
  15. IDEA向前向后箭头,左右箭头如何设置
  16. mac php pear,OSX EI Captain中安装Pear等三方软件不成功的解决方法
  17. itextpdf 添加折线图、饼图、柱状图
  18. 苹果商店ASA广告投放之TTR和CR
  19. 【Git】Git获取Commit修改文件列表
  20. 在微软从测试开发工程师到主管

热门文章

  1. Lambda 表达式入门,这篇够了!
  2. 我的天!你竟然没有在SpringBoot中使用过异步请求和异步调用...
  3. c#调用python脚本效率,C#调用Python脚本 C#调用Python脚本的简单示例
  4. 24 内置函数 命名元组(namedtuple) ,os ,sys,序列化,pickle,json
  5. javascript 编程指南
  6. C语言 文件操作5--文件的常用函数
  7. 学习是一件高尚而孤独的事情
  8. VS2010制作dll
  9. iOS应用审核的通关秘籍
  10. Android开发工程师,前行路上的14项技能