Description
Solutioin
推一波式子,容易将一个操作写成一次函数的形式。
现在只需要对于每个操作计算所有可能在它后面的操作对它的影响,也就是斜率乘积乘上这种情况出现的概率。
考虑分治NTT
但此时我们发现需要对于每一个操作求和,且自己不能选。
有一个很妙的做法,分治NTT的时候对于两边分别维护全选上的和缺一个的和
左边缺一个 * 右边全选 + 右边缺一个 * 左边全选就是整个区间缺一个的和
这样就 O ( n log 2 n ) O(n\log^2n) O(nlog2n)做完了
Code
#include <cstdio>
#include <cstdlib>
#include <iostream>
#include <cmath>
#include <algorithm>
#include <cstring>
#define fo(i,a,b) for(int i=a;i<=b;++i)
#define fod(i,a,b) for(int i=a;i>=b;--i)
#define mo 998244353
#define LL long long
#define N 100005
#define M 262144
using namespace std;
int n,st[N],le[N],bit[M+1],n1,cf[21],l2[M+1];
LL a[M+1],u1[M+1],u2[M+1],u3[M+1],u4[M+1],wi[M+1],wg[M+1],ny,a1[N][3],js[N],b[M+1];
LL ksm(LL k,LL n)
{
LL s=1;
for(;n;n>>=1,k=k*k%mo) if(n&1) s=s*k%mo;
return s;
}
void prp(int num)
{
fo(i,0,num)
{
bit[i]=(bit[i>>1]>>1)|((i&1)<<(l2[num]-1));
wi[i]=wg[i*(M/num)];
}
ny=ksm(num,mo-2);
}
void NTT(LL *a,bool pd,int num)
{
fo(i,0,num-1) if(i<bit[i]) swap(a[i],a[bit[i]]);
LL v;
for(int lim=num>>1,m=2,half=1;m<=num;half=m,lim>>=1,m<<=1)
{
LL wn=(!pd)?wi[lim]:wi[num-lim];
for(int j=0;j<num;j+=m)
{
LL w=1;
for(int i=0;i<half;++i,w=w*wn%mo)
{
v=w*a[i+j+half]%mo;
a[i+j+half]=(a[i+j]-v+mo)%mo;
a[i+j]=(a[i+j]+v)%mo;
}
}
}
if(pd) fo(i,0,num-1) a[i]=a[i]*ny%mo;
}
void doit(int l,int r)
{
if(l==r) return;
int mid=(l+r)>>1;
doit(l,mid),doit(mid+1,r);
int num=cf[l2[le[l]+le[mid+1]]];
fo(i,0,num-1) u1[i]=u2[i]=u3[i]=u4[i]=0;
fo(i,0,le[l]-1) u1[i]=a[st[l]+i],u3[i]=b[st[l]+i];
fo(i,0,le[mid+1]-1) u2[i]=a[st[mid+1]+i],u4[i]=b[st[mid+1]+i];
prp(num);
NTT(u1,0,num),NTT(u2,0,num),NTT(u3,0,num),NTT(u4,0,num);
fo(i,0,num-1)
{
u3[i]=(u3[i]*u2[i]+u4[i]*u1[i])%mo;
u1[i]=u1[i]*u2[i]%mo;
}
NTT(u1,1,num),NTT(u3,1,num);
le[l]=min(2*n+1,le[l]+le[mid+1]-1);
fo(i,0,le[l]) a[st[l]+i]=u1[i],b[st[l]+i]=u3[i];
}
int main()
{
cin>>n;
fo(i,1,n) scanf("%lld%lld%lld",&a1[i][0],&a1[i][1],&a1[i][2]);
LL vn=1;
fo(i,1,n) vn=vn*(LL)i%mo;
vn=ksm(vn,mo-2);
fo(i,1,n)
{
st[i]=n1;
le[i]=2;
a[n1]=1;
b[n1]=a1[i][1]*a1[i][0]%mo;
a[++n1]=((1-a1[i][0]+mo)%mo*a1[i][2]%mo+a1[i][0])%mo;
b[n1]=0;
n1++;
}
wg[0]=1;
LL v=ksm(3,(mo-1)/M);
fo(i,1,M) wg[i]=wg[i-1]*v%mo;
cf[0]=1;
fo(i,1,18) cf[i]=cf[i-1]<<1,l2[cf[i]]=i;
fod(i,M-1,2) if(!l2[i]) l2[i]=l2[i+1];
doit(1,n);
LL ans=0;
js[0]=1;
fo(i,1,n) js[i]=js[i-1]*(LL)i%mo;
fo(i,0,n-1) ans=(ans+b[st[1]+i]*js[i]%mo*js[n-i-1]%mo)%mo;
printf("%lld\n",vn*ans%mo);
}