【LOJ565】【LibreOJ Round #10】mathematican 的二进制

SOL:

  1.我们发现如果进行k次操作,最后结果为v,那么代价=2*k-bitcount(v)

  2.我们发现ans=2* 概率和 - bitcount(所有操作的数)的期望

  3.所有操作的顺序互相无关。

那么我们按位操作,从低向高DP。

同一位上分治NTT,不同位上DP+NTT转移。

#include<bits/stdc++.h>
#define mo 998244353
#define LL long long
#define pii pair<int,int>
#define x first
#define y second
#define pb push_back
#define N 800207
using namespace std;
#define sight(x) ('0'<=x&&x<='9')
inline void read(int &x){
    static char c;
    for (c=getchar();!sight(c);c=getchar());
    for (x=0;sight(c);c=getchar())x=x*10+c-48;
}
inline LL qsm(LL x,LL y=mo-2){
    static LL anw;
    for (anw=1;y;y>>=1,x=x*x%mo) if (y&1) anw=anw*x%mo;
    return anw;
}
LL l[N],n[N];int D[N]; 
void Pre() {
    for (int i=1;i<N;i++) l[i]=qsm(3,(mo-1)/i/2),n[i]=qsm(l[i]);
}
LL wn,w,Xx,Yy;
inline void NTT(vector<LL> &X,int x,int m){static LL gg;
     m=1<<m;gg=qsm(m);
    for (int i=0;i<m;i++) if (i<D[i]) swap(X[i],X[D[i]]);
    for (int i=1;i<m;i<<=1) {
        wn=x?l[i]:n[i]; w=1; 
        for (int j=0;j<m;j+=i<<1,w=1) 
         for (int k=j;k<j+i;k++,w=w*wn%mo) {
             Xx=X[k]; Yy=X[k+i]*w%mo;
             X[k]=(Xx+Yy)%mo; X[k+i]=(Xx-Yy+mo)%mo;
         }    
    }
    if (!x) for (int i=0;i<m;i++) X[i]=X[i]*gg%mo;
} 
struct Poly{
    vector<LL> poly;
    int len;
    Poly() {len=0; poly.clear(); poly.pb(1);}
    void clear(){len=0; poly.clear(); poly.pb(1);}
    void mul(Poly &A,Poly &B){
        static int m;
        len=B.len+A.len;
        for (m=0;1<<m<=len;m++);
        poly.resize(1<<m); 
        A.poly.resize(1<<m);  B.poly.resize(1<<m);
        for (int i=1;i<(1<<m);i++) D[i]=D[i>>1]>>1|((i&1)<<m-1);
         NTT(A.poly,1,m); NTT(B.poly,1,m); 
        for (int i=0;i<(1<<m);i++) poly[i]=A.poly[i]*B.poly[i]%mo;
        NTT(poly,0,m);
        A.clear(); B.clear();
    }
    void out() {
        for (int i=len;~i;i--) printf("%lld ",poly[i]);puts("");
    }
}P[N],g[N],Pta,*f=g+1;
pii p[N];
#define Mid (l+r>>1)
void sol(int no,int l,int r){
    if (l==r) { P[no].len=1; P[no].poly[0]=1+mo-p[l].y; P[no].poly.pb(p[l].y); return;}
    sol(no<<1,l,Mid),sol(no<<1|1,Mid+1,r);
    P[no].mul(P[no<<1],P[no<<1|1]);
}
int ll,r;
int Nn,m;
LL ans;
signed main () {
//    freopen("c.in","r",stdin);
    Pre(); //f[0].poly.pb(1); 
    read(Nn); read(m);
    for (int i=1;i<=m;i++) 
     read(p[i].x),read(ll),read(r),p[i].y=1ll*ll*qsm(r)%mo,
    ans+=2*p[i].y;
    sort(p+1,p+m+1);
    ans%=mo; r=0;
    for (int i=0;i<=Nn+20;i++) {
      ll=r+1; 
       if (p[ll].x==i) while (p[r+1].x==i&&r<m) r++;
       Pta.poly.resize((f[i-1].len>>1)+1);
       Pta.len=f[i-1].len>>1;
       assert(f[i-1].poly.size()>=f[i-1].len+1);
       for (int j=0;j<=f[i-1].len;j+=2) {
        Pta.poly[j>>1]=f[i-1].poly[j];
        if (j+1<=f[i-1].len)  ans-=f[i-1].poly[j+1],ans%=mo,
         Pta.poly[j>>1]+=f[i-1].poly[j+1],Pta.poly[j>>1]%=mo;
      } 
      if (p[ll].x==i) sol(1,ll,r);
      f[i].mul(P[1],Pta);
     } 
    printf("%lld\n",(ans%mo+mo)%mo);
    return 0;
}

 

posted @ 2018-07-14 16:29  泪寒之雪  阅读(387)  评论(0编辑  收藏  举报