1 条题解

  • 0
    @ 2026-5-17 14:25:40
    #include<bits/stdc++.h>
    #define ll long long
    using namespace std;
    #define I ll
    #define her1 20081214
    #define IV void
    #define cht 998244353
    #define ld long double
    #define Aestas16 392699
    #define ull unsigned long long
    #define cp(x,y)memcpy(x,y,sizeof y)
    #define mem(x,val)memset(x,val,sizeof x)
    #define D(i,j,n)for(register int i=j;i>=n;i--)
    #define E(i,now)for(register int i=first[now];i;i=e[i].nxt)
    #define F(i,j,n)for(register int i=j;i<=n;i++)
    #define DL(i,j,n)for(register i64 i=j;i>=n;i--)
    #define EL(i,now)for(register i64 i=first[now];i;i=e[i].nxt)
    #define FL(i,j,n)for(register i64 i=j;i<=n;i++)
    ll read(){
    	ll ans=0,f=1;
    	char c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-')f=-1;
    		c=getchar();
    	}
    	while(c>='0'&&c<='9')ans=ans*10+c-'0',c=getchar();
    	return ans*f;
    }
    #undef ll
    #include "assert.h"
    mt19937_64 rnd(her1);
    #include "functional"
    using i64 = long long;
    const int MAX = (1<<19);
    const int maxn = (1<<19)+5;
    const int maxm = (1<<19)+5;
    #define in(i,V) F(i,0,(i64)V.size()-1)
    #define My_assert(expr,tips) ((expr)?(void(0)):(puts(tips),exit(0)))
    IV cadd(i64&x,i64 val){x=(x+val)%cht;}
    
    i64 w[maxm];
    i64 qpow(i64 n,i64 base=cht-2){
    	i64 ans=1;
    	while(base){
    		if(base&1)ans=ans*n%cht;
    		n=n*n%cht;base>>=1;
    	}
    	return ans;
    }
    IV init(i64 limit){
    	for(int i=1,j,k;i<limit;i<<=1)
    		for(w[j=i]=1,k=qpow(3,(cht-1)/(i<<1)),j++;j<(i<<1);j++)
    			w[j]=w[j-1]*k%cht;
    }
    IV DIT(i64*a,i64 limit){
    	for(i64 i,j,k=limit>>1,L,*W,*x,*y,z;k;k>>=1)
    		for(L=k<<1,i=0;i<limit;i+=L)for(j=0,W=w+k,x=a+i,y=x+k;j<k;j++,W++,x++,y++)
    			*y=(*x+cht-(z=*y))* *W%cht,*x=(*x+z)%cht;
    }
    IV DIF(i64*a,i64 limit){
    	for(i64 i,j,k=1,L,*W,*x,*y,z;k<limit;k<<=1)
    		for(L=k<<1,i=0;i<limit;i+=L)for(j=0,W=w+k,x=a+i,y=x+k;j<k;j++,W++,x++,y++)
    			z=1ll* *W* *y%cht,*y=(*x-z)%cht,*x=(*x+z)%cht;
    	reverse(a+1,a+limit);
    	i64 inv=qpow(limit);
    	F(i,0,limit-1)a[i]=a[i]*inv%cht;
    }
    #define poly vector<i64>
    IV adjust(poly&C){
    	while(C.size()&&!C.back())
    		C.pop_back();
    }
    poly operator*(const poly&A,const poly&B){
    	if(A.empty()||B.empty())return{};
    	if(A.size()<=5||B.size()<=5){
    		poly C(A.size()+B.size()-1);
    		in(i,A)in(j,B)cadd(C[i+j],A[i]*B[j]);
    		adjust(C);return C;
    	}
    	static i64 f[maxm],g[maxm];
    	My_assert(A.size()&&B.size(),"multiply with a empty poly.");
    	i64 limit=1;
    	while(limit<=A.size()+B.size())
    		limit<<=1;
    	F(i,0,limit-1)f[i]=g[i]=0;
    	in(i,A)f[i]=A[i];in(i,B)g[i]=B[i];
    	DIT(f,limit);DIT(g,limit);
    	F(i,0,limit-1)f[i]=f[i]*g[i]%cht;DIF(f,limit);
    	poly C;C.resize(A.size()+B.size()-1);
    	in(i,C)C[i]=f[i];adjust(C);return C;
    }
    poly operator+(const poly&A,const poly&B){
    	poly C;C.resize(max(A.size(),B.size()));
    	in(i,C)C[i]=0;
    	in(i,A)cadd(C[i],A[i]);
    	in(i,B)cadd(C[i],B[i]);
    	return C;
    }
    poly operator-(const poly&A,const poly&B){
    	poly C;C.resize(max(A.size(),B.size()));
    	in(i,C)C[i]=0;
    	in(i,A)cadd(C[i],A[i]);
    	in(i,B)cadd(C[i],-B[i]);
    	return C;
    }
    i64 fac[maxn],ifac[maxn];
    IV init(){
    	fac[0]=1;F(i,1,MAX)fac[i]=fac[i-1]*i%cht;
    	ifac[MAX]=qpow(fac[MAX]);D(i,MAX-1,0)ifac[i]=ifac[i+1]*(i+1)%cht;
    }
    IV remod(poly&A,i64 n){while(A.size()>n)A.pop_back();}
    IV print(poly v){
    	for(auto x:v)cout<<x<<' ';
    	puts("");
    }
    poly binom_poly(i64 nw){
    	poly Tmp(nw+1);
    	F(i,0,nw)Tmp[i]=((i&1)?-1:1)*fac[nw]*ifac[i]%cht*ifac[nw-i]%cht;
    	return Tmp;
    }
    struct frac{
    	poly p;i64 k;
    	IV adjust(i64 nw){
    		assert(k<=nw);if(k==nw)return;nw-=k;
    		p=p*binom_poly(nw);k+=nw;
    	}
    };
    frac operator*(const frac&A,const frac&B){return{A.p*B.p,A.k+B.k};}
    frac operator+(frac A,frac B){
    	i64 nw=max(A.k,B.k);
    	A.adjust(nw);B.adjust(nw);
    	return{A.p+B.p,nw};
    }
    frac operator-(frac A,frac B){
    	i64 nw=max(A.k,B.k);
    	A.adjust(nw);B.adjust(nw);
    	return{A.p-B.p,nw};
    }
    struct nfrac{poly p,q;};
    nfrac operator*(const nfrac&A,const nfrac&B){return{A.p*B.p,A.q*B.q};}
    nfrac operator/(const nfrac&A,const nfrac&B){return{A.p*B.q,A.q*B.p};}
    nfrac operator+(const nfrac&A,const nfrac&B){
    	return{A.p*B.q+A.q*B.p,A.q*B.q};
    }
    nfrac operator-(const nfrac&A,const nfrac&B){
    	return{A.p*B.q-A.q*B.p,A.q*B.q};
    }
    nfrac Make(frac x){
    	return{x.p,binom_poly(x.k)};
    }
    i64 n,m,A[maxn],B[maxn],C[maxn],D[maxn];
    frac make(poly A){adjust(A);return{A,0};}
    struct node{frac A,B,C,D;}t1,t2;
    node operator+(const node&X,const node&Y){
    	return{X.A+Y.A,X.B+Y.B,X.C+Y.C,X.D+Y.D};
    }
    node operator*(const node&X,const frac&k){
    	return{X.A*k,X.B*k,X.C*k,X.D*k};
    }
    pair<node,node>cdq(i64 l,i64 r){
    	if(l==r){
    		t1.A.k=t1.B.k=t1.C.k=t1.D.k=0;
    		t1.A=make(poly{0,B[l]});
    		t1.B=make(poly{0,C[l]});
    		t1.C=make(poly{0,D[l]});
    		t1.D=make(poly{l==n});
    		if(A[l]){
    			t1.A.k++;
    			t1.B.k++;
    			t1.C.k++;
    			t1.D.k++;
    		}
    		t2.A=make(poly{1});
    		t2.B=t2.C=t2.D=make(poly{});
    		return{t1,t2};
    	}
    	i64 mid=l+r>>1;
    	auto[vl,vlis]=cdq(l,mid);
    	auto[vM,vMis]=cdq(mid+1,r);
    	auto gen=[&](node v)->node{
    		node nw=vM*v.A+vMis*v.B;
    		nw.C=nw.C+v.C;nw.D=nw.D+v.D;
    		return nw;
    	};
    	return make_pair(gen(vl),gen(vlis));
    }
    i64 Bostan_Mori(poly f,poly g,i64 n){
    	while(n){
    		poly ig=g;in(i,g)if(i&1)ig[i]=-ig[i];
    		f=f*ig;g=g*ig;
    		poly nf,ng;
    		in(i,f)if((i&1)==(n&1))nf.push_back(f[i]);
    		in(i,g)if(i%2==0)ng.push_back(g[i]);
    		n>>=1;
    		f=nf;g=ng;
    	}
    	if(f.empty())return 0;
    	return f[0]*qpow(g[0])%cht;
    }
    int main(){
    	init();init(1<<19);
    	n=read();m=read();
    	F(i,1,n)A[i]=read();
    	F(i,1,n)B[i]=read();
    	F(i,1,n)C[i]=read();
    	F(i,1,n)D[i]=read();
    	D[1]=0;
    	node Tmp=cdq(1,n).first;
    	nfrac Ans=Make(Tmp.D)/Make((make(poly{1})-Tmp.C));
    	cout<<(Bostan_Mori(Ans.p,Ans.q,m)+cht)%cht;
    	return 0;
    }
    
    • 1

    信息

    ID
    8858
    时间
    8000ms
    内存
    1024MiB
    难度
    7
    标签
    递交数
    27
    已通过
    9
    上传者