原文链接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 <bits/stdc++.h>
#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" = "<<x<<endl
#define outtag(x) cerr<<"---------------"#x"---------------"<<endl
#define outarr(a,L,R) cerr<<#a"["<<L<<".."<<R<<"] = ";\
For(_x,L,R)cerr<<a[_x]<<" ";cerr<<endl;
using namespace std;
typedef long long LL;
typedef vector <int> 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<<d)<n)
d++;
For(i,0,n-1)
R[i]=(R[i>>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<R[i])
swap(a[i],a[R[i]]);
for (int t=n>>1,d=1;d<n;d<<=1,t>>=1)
for (int i=0;i<n;i+=d<<1)
for (int j=0;j<d;j++){
int tmp=(LL)w[t*j]*a[i+j+d]%mod;
a[i+j+d]=Del(a[i+j]-tmp);
Add(a[i+j],tmp);
}
if (flag<0){
reverse(w+1,w+n);
int inv=Pow(n,mod-2);
For(i,0,n-1)
a[i]=(LL)a[i]*inv%mod;
}
}
}
using fft::FFT;
int n,m;
vi a[N],p[N];
vi operator * (vi A,vi B){
static int a[N],b[N];
int n=1;
while (n<A.size()+B.size())
n<<=1;
For(i,0,n-1)
a[i]=b[i]=0;
For(i,0,(int)A.size()-1)
a[i]=A[i];
For(i,0,(int)B.size()-1)
b[i]=B[i];
fft::init(n);
FFT(a,n,1),FFT(b,n,1);
For(i,0,n-1)
a[i]=(LL)a[i]*b[i]%mod;
FFT(a,n,-1);
vi ans;
For(i,0,n-1)
ans.pb(a[i]);
while (ans.size()>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<<ans<<endl;
return 0;
}

LOJ#565. 「LibreOJ Round #10」mathematican 的二进制 分治,FFT,概率期望的更多相关文章

  1. #565. 「LibreOJ Round #10」mathematican 的二进制(期望 + 分治NTT)

    题面 戳这里,题意简单易懂. 题解 首先我们发现,操作是可以不考虑顺序的,因为每次操作会加一个 \(1\) ,每次进位会减少一个 \(1\) ,我们就可以考虑最后 \(1\) 的个数(也就是最后的和) ...

  2. LOJ565. 「LibreOJ Round #10」mathematican 的二进制(NTT)

    题目链接 https://loj.ac/problem/565 题解 首先,若进行所有操作之后成功执行的操作数为 \(m\),最终得到的数为 \(w\),那么发生改变的二进制位的数量之和(即代价之和) ...

  3. [LOJ#531]「LibreOJ β Round #5」游戏

    [LOJ#531]「LibreOJ β Round #5」游戏 试题描述 LCR 三分钟就解决了问题,她自信地输入了结果-- > -- 正在检查程序 -- > -- 检查通过,正在评估智商 ...

  4. [LOJ#530]「LibreOJ β Round #5」最小倍数

    [LOJ#530]「LibreOJ β Round #5」最小倍数 试题描述 第二天,LCR 终于启动了备份存储器,准备上传数据时,却没有找到熟悉的文件资源,取而代之的是而屏幕上显示的一段话: 您的文 ...

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

    [LOJ#516]「LibreOJ β Round #2」DP 一般看规律 试题描述 给定一个长度为 \(n\) 的序列 \(a\),一共有 \(m\) 个操作. 每次操作的内容为:给定 \(x,y\ ...

  6. [LOJ#515]「LibreOJ β Round #2」贪心只能过样例

    [LOJ#515]「LibreOJ β Round #2」贪心只能过样例 试题描述 一共有 \(n\) 个数,第 \(i\) 个数 \(x_i\) 可以取 \([a_i , b_i]\) 中任意值. ...

  7. [LOJ#525]「LibreOJ β Round #4」多项式

    [LOJ#525]「LibreOJ β Round #4」多项式 试题描述 给定一个正整数 k,你需要寻找一个系数均为 0 到 k−1 之间的非零多项式 f(x),满足对于任意整数 x 均有 f(x) ...

  8. [LOJ#526]「LibreOJ β Round #4」子集

    [LOJ#526]「LibreOJ β Round #4」子集 试题描述 qmqmqm有一个长为 n 的数列 a1,a2,……,an,你需要选择集合{1,2,……,n}的一个子集,使得这个子集中任意两 ...

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

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

随机推荐

  1. VS 引用dll版本冲突问题

    1.删除项目中的对应引用: 2.如果是有用到NetGet引用的删除项目中的packages里面的对应包文件: 3.如果是在NetGet中引用的注释项目中packages.config对应的插件名: 4 ...

  2. MSMQ消息加密

    证书实现非对称加密/解密的代码如下 //非对称加密密钥 static byte[] RSAEncrypt(byte[] enkey, X509Certificate2 Certificate) { R ...

  3. 1 集群状态、增删改查、全量替换、强制创建、设置单个index的分片数副本数

    检查集群健康状态,可以看集群颜色.(黄色:primary shard都正常,replica不正常) GET /_cat/health?v 列出集群所有index GET /_cat/indices?v ...

  4. 2019北航OO第三单元作业总结

    1.梳理JML语言的理论基础.应用工具链情况 JML基础理论: JML(Java Modeling Language)是用于对Java程序进行规格化设计的一种表示语言.JML是一种行为接口规格语言,基 ...

  5. mysql的左连接问题

    之前写过一个mysql语句,功能是将一个表ds的一个字段值同步更新到另一个表bk的字段,不过不是全部,只更新表bk中有的数据,如果表bk中有而表ds中没有,表B对应的这个字段值就为空 UPDATE b ...

  6. M - Ordering Tasks(拓扑排序)

    M - Ordering Tasks Time Limit:3000MS     Memory Limit:0KB     64bit IO Format:%lld & %llu Descri ...

  7. 【zookeeper】apache-zookeeper-3.5.5的安装测试

    下载:apache-zookeeper-3.5.5.tar.gz 进入zookeeper安装目录查看lib文件夹和zookeeper-3.5.5.jar是否存在,如果没有需要手动添加,不然启动时会报错 ...

  8. UEditor 在 Layer 模态框中无法使用问题

    问题: 解决方法: 在 使用  ueditor 的页面顶部加入js代码: window.UEDITOR_HOME_URL = "__STATIC__/path/to/ueditor/&quo ...

  9. CentOS7.x安装Java

    1.在甲骨文注册帐号下载需要版本的java的源码包 https://www.oracle.com/java/technologies/jdk12-downloads.html 2.把下载好的jdk的源 ...

  10. atoi()和itoa()函数详解以及C语言实现

    atoi()函数 atoi()原型:  int atoi(const char *str ); 函数功能:把字符串转换成整型数. 参数str:要进行转换的字符串 返回值:每个函数返回 int 值,此值 ...