博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LOJ#565. 「LibreOJ Round #10」mathematican 的二进制 分治,FFT,概率期望
阅读量:4983 次
发布时间:2019-06-12

本文共 2368 字,大约阅读时间需要 7 分钟。

原文链接www.cnblogs.com/zhouzhendong/p/LOJ565.html

前言

标算真是优美可惜这题直接暴力FFT算一算就solved了。

题解

首先,假装没有进位,考虑解决这个问题。

对于每一位,考虑作用在其之上的概率为 \(p\) 的操作,构建多项式 \(((1-p) + px )\),那么将一个位置上所有这样的多项式乘起来之后, \(x^k\) 项系数就代表这个位置被操作 \(k\) 次的概率。对答案的贡献就是 \(k\times\) \(x^k\) 项系数。

考虑进位。

从低位向高位推,进位就相当于将多项式系数两个两个合并。

从低位向高位,考虑将每一位的多项式两个两个合并之后乘到高一位的多项式上,就可以得出每一位被变换任意次的真的概率。

考虑这个过程的复杂度:

一个多项式的长度对其高位长度的贡献依次是 $len, len / 2, len / 4, len / 2 ^ 3 ,\cdots $ ,所以总贡献是 \(O(len)\) 的。由于多项式总长度为 \(O(n+m)\) ,又由于乘法在FFT时有个log,所以这部分的总时间复杂度为 \(O((n+m)\log m)\)

而前一半需要分治FFT来算多项式,复杂度为 \(O(m\log ^ 2m)\)

总时间复杂度为 \(O(n\log m + m\log ^ 2 m)\)

代码

#include 
#define clr(x) memset(x,0,sizeof x)#define For(i,a,b) for (int i=(a);i<=(b);i++)#define Fod(i,b,a) for (int i=(b);i>=(a);i--)#define fi first#define se second#define pb(x) push_back(x)#define mp(x,y) make_pair(x,y)#define outval(x) cerr<<#x" = "<
<
vi;LL read(){ LL x=0,f=0; char ch=getchar(); while (!isdigit(ch)) f|=ch=='-',ch=getchar(); while (isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar(); return f?-x:x;}const int N=1<<19,mod=998244353;int Pow(int x,int y){ int ans=1; for (;y;y>>=1,x=(LL)x*x%mod) if (y&1) ans=(LL)ans*x%mod; return ans;}void Add(int &x,int y){ if ((x+=y)>=mod) x-=mod;}void Del(int &x,int y){ if ((x-=y)<0) x+=mod;}int Add(int x){ return x>=mod?x-mod:x;}int Del(int x){ return x<0?x+mod:x;}namespace fft{ int w[N],R[N]; void init(int n){ int d=0; while ((1<
>1]>>1)|((i&1)<<(d-1)); w[0]=1,w[1]=Pow(3,(mod-1)/n); For(i,2,n-1) w[i]=(LL)w[i-1]*w[1]%mod; } void FFT(int *a,int n,int flag){ if (flag<0) reverse(w+1,w+n); For(i,0,n-1) if (i
>1,d=1;d
<<=1,t>>=1) for (int i=0;i
<<1) for (int j=0;j
1&&!ans.back()) ans.pop_back(); return ans;}vi build(int *a,int L,int R){ if (L==R) return (vi){Del(1-a[L]),a[L]}; int mid=(L+R)>>1; vi lp=build(a,L,mid); vi rp=build(a,mid+1,R); return lp*rp;}void Getp(int x){ int s=a[x].size(); if (!s) p[x]=(vi){1}; else p[x]=build(&a[x][0],0,s-1);}int main(){ n=read()+23,m=read(); For(i,1,m){ int p=read(),x=read(),y=read(); x=(LL)x*Pow(y,mod-2)%mod; a[p].pb(x); } int ans=0; For(i,0,n){ Getp(i); if (i>0) p[i]=p[i]*p[i-1]; For(j,0,(int)p[i].size()-1) Add(ans,(LL)p[i][j]*j%mod); if (p[i].size()&1) p[i].pb(0); int s=p[i].size()/2; For(j,0,s-1) p[i][j]=Add(p[i][j*2]+p[i][j*2+1]); while (p[i].size()>s) p[i].pop_back(); } cout<
<

转载于:https://www.cnblogs.com/zhouzhendong/p/LOJ565.html

你可能感兴趣的文章
.net 数据库缓存依赖:【实例与解释】
查看>>
Android Service小试 启动和停止service
查看>>
一天一个设计模式:适配器模式
查看>>
第5题 查找字符串中的最长回文字符串---Manacher算法
查看>>
HDOJ 1069 Monkey and Banana 解题报告
查看>>
11锚点与图像对象
查看>>
Ios中比较两个日期之间的时间差距
查看>>
jQuery基础选择器
查看>>
寒假作业03
查看>>
P1129 [ZJOI2007]矩阵游戏
查看>>
hdu2046 骨牌铺方格
查看>>
Linux下mysql启动失败
查看>>
同心圆闪烁扩散功能
查看>>
oracle 如何恢复误删的表记录数据
查看>>
Druid连接池错误(数据库版本问题)
查看>>
console对象-转
查看>>
洛谷 4216 BZOJ 4448 [SCOI2015]情报传递
查看>>
清北学堂2018DP&图论精讲班 DP部分学习笔记
查看>>
css3 2D变换 transform
查看>>
Fastjson获取天气信息封装bean
查看>>