[CTSC2018] green mushroom Lord

[CTSC2018] green mushroom Lord 

answer

First of all, we want to know what the conclusion consecutive segments:

Continuous cross section or not, comprising either

So is a tree! each father position is behind it comprises a first

Tree DP!

Provided dp [x], x is the root of the subtree (interval length is set len ​​Territories, i.e. L [X]), with 1 ~ len of fillers to meet the number of programs L

That is, each son inside legitimate,

Son assigned to each reference section, such that together draw a not adjacent son

We will not draw a line together?

 So you can put each son as a single point, it became classified as: 1,1,1,1, ... a number of programs len!

 

Set f [i] denotes a length of 1,1,1,1 .... i + 1 legitimate program sequence number i + 1 is.

$dp[x]=(\Pi dp[son])\times f[L[x]]$

Summarize, we can get $ ans = \ Pi f [| son (x) |] $, $ | son (x) | $ x denotes the number of sons

 

Request f [n]?

Consider become inverse arrangement!

(I.e. the horizontal and vertical coordinates mapping matrix Significance exchange)

Thus, n + 1 becomes a natural segmentation points.

 

f [n-1], the value of 1

Either legitimate before.

Either something separate 1

| Son (x) | monotonous stack directly

 

Note, Poly each clear need to re-resize

 

#include<bits/stdc++.h>
#define reg register int
#define il inline
#define fi first
#define se second
#define mk(a,b) make_pair(a,b)
#define numb (ch^'0')
#define pb push_back
#define solid const auto &
#define enter cout<<endl
#define pii pair<int,int>
using namespace std;
typedef long long ll;
template<class T>il void rd(T &x){
    char ch;x=0;bool fl=false;while(!isdigit(ch=getchar()))(ch=='-')&&(fl=true);
    for(x=numb;isdigit(ch=getchar());x=x*10+numb);(fl==true)&&(x=-x);}
template<class T>il void output(T x){if(x/10)output(x/10);putchar(x%10+'0');}
template<class T>il void ot(T x){if(x<0) putchar('-'),x=-x;output(x);putchar(' ');}
template<class T>il void prt(T a[],int st,int nd){for(reg i=st;i<=nd;++i) ot(a[i]);putchar('\n');}
namespace Modulo{
const int mod=998244353;
int ad(int x,int y){return (x+y)>=mod?x+y-mod:x+y;}
void inc(int &x,int y){x=ad(x,y);}
int sub(int x,int y){return ad(x,mod-y);}
int mul(int x,int y){return (ll)x*y%mod;}
void inc2(int &x,int y){x=mul(x,y);}
int qm(int x,int y=mod-2){int ret=1;while(y){if(y&1) ret=mul(x,ret);x=mul(x,x);y>>=1;}return ret;}
template<class ...Args>il int ad(const int a,const int b,const Args &...args) {return ad(ad(a,b),args...);}
template<class ...Args>il int mul(const int a,const int b,const Args &...args) {return mul(mul(a,b),args...);}
}  
using namespace Modulo;
namespace Miracle{
const int N=50000+5;
const int G=3;
const int GI=332748118;
int n,T;
int L[N];
struct Poly{
    vector<int>f;
    Poly(){f.clear();}
    il int &operator[](const int &x){assert(x<f.size());return f[x];}
    il void resize(int n){f.resize(n);}
    il int size(){return f.size();}
    il void clear(){f.clear();}
    il void out(){for(reg i=0;i<(int)f.size();++i) ot(f[i]);putchar('\n');}
}f;
int rev[8*N];
int init(int n){
    int m=0;
    for(m=1;m<n;m<<=1);
    for(reg i=0;i<m;++i){
        rev[i]=(rev[i>>1]>>1)|((i&1)?m>>1:0);
    }
    return m;
}
void NTT(Poly &f,int c){
    int n=f.size();
    for(reg i=0;i<n;++i){
        if(i<rev[i]) swap(f[i],f[rev[i]]);
    }
    for(reg p=2;p<=n;p<<=1){
        int gen;
        if(c==1) gen=qm(G,(mod-1)/p);
        else gen=qm(GI,(mod-1)/p);
        for(reg l=0;l<n;l+=p){
            int buf=1;
            for(reg i=l;i<l+p/2;++i){
                int tmp=mul(f[i+p/2],buf);
                f[i+p/2]=ad(f[i],mod-tmp);
                f[i]=ad(f[i],tmp);
                buf=mul(buf,gen);
            }
        }
    }
    if(c==-1){
        int iv=qm(n);
        for(reg i=0;i<n;++i){
            f [i] = u (f [i], iv);
        }
    }
}
il Poly operator *(Poly F,Poly G){
    int n=init(F.size()+G.size()-1);
    F.resize(n);G.resize(n);
    NTT(F,1);NTT(G,1);
    for(reg i=0;i<n;++i) F[i]=mul(F[i],G[i]);
    NTT(F,-1);
    return F;
}
void division ( you have to, you r) {
    
    if(l==0&&r==1){
        f[0]=1;f[1]=2;return;
    }
    if(l==r){
        in [] = ad (f [t], as mul (f [ 1 ], in [the first ], the 2 ));
        in [] = ad (f [t], composed (the first , in [the first ]));
        return ;
    }
    int mid=(l+r)>>1;
    divi(l,mid);
    // cout<<" divi ---------------------------"<<l<<" "<<r<<endl;
    Poly F,G,K;
    if(l==0){
        // goto s;
        // cout<<"sol1---- "<<endl;
        F.resize(mid+1);
        G.resize(mid+1);
        for(reg i=1;i<=mid;++i){
            F[i]=f[i];
            G[i]=mul(f[i],i-1);
        }
        // F.out();
        // G.out();
        // cout<<"hahahaha "<<endl;
        F=F*G;
        // F.out();
        
        for(reg i=mid+1;i<=r;++i){
            f [i] = to (f [i], F [i]);
        }
        // cout<<" over "<<endl;
    }else{
        
        // cout<<"sol2**** "<<endl;
        F.resize(mid-l+1);
        G.resize(r-l+1);
        for(reg i=0;i<=mid-l;++i){
            F[i]=f[i+l];
        }
        for(reg i=1;i<=r-l;++i){
            G[i]=mul(f[i],i-1);
        }
        // F.out();
        // G.out();
        // cout<<" mul "<<endl;
        K=F*G;
        // cout<<" K "<<endl;
        // K.out();

        for(reg i=mid+1;i<=r;++i){
            f [i] = to (f [i], K [i- l]);
        }
        
        F.clear();G.clear();
        F.resize(mid-l+1);G.resize(r-l+1);

        // cout<<F.size()<<" len "<<mid-l+1<<endl;
        for(reg i=0;i<=mid-l;++i){
            F[i]=mul(f[i+l],i+l-1);
        }
        // cout<<" OK ? "<<endl;
        for(reg i=1;i<=r-l;++i){
            G[i]=f[i];
        }
        
        K=F*G;
        for(reg i=mid+1;i<=r;++i){
            f [i] = to (f [i], K [i- l]);
        }
    }
    // s:;
    // cout<<" end "<<f[3]<<endl;
    divi(mid+1,r);
}
int sta[N],top;
int main(){
    rd (T); rd (n);
    int m=init(n+1);
    f.resize(m);
    
    divi(0,m-1);
    // f.out();

    while(T--){
        for(reg i=1;i<=n;++i) rd(L[i]);
        top=0;
        if(L[n]!=n) {
            puts("0");continue;
        }
        int ans=1;
        bool fl=true;
        for(reg i=1;i<=n;++i){
            int son=0;
            while(top&&sta[top]-L[sta[top]]+1>=i-L[i]+1) ++son,--top;
            // cout<<" ii "<<i<<" son "<<son<<endl;
            if(top){
                if(sta[top]>=i-L[i]+1) fl=false;
            }
            sta[++top]=i;
            years = mul (years f [his]);
        }
        if(!fl) ans=0;
        printf("%d\n",ans);
    }
    return 0;
}

}
signed main(){
    Miracle::main();
    return 0;
}

/*
   Author: *Miracle*
*/

The tree!

Then recursively into sub-problems.

Recursively into sub-problems, the. . . As. . . .

Essentially "cut point" to find a similar structure. Or induction

 

Guess you like

Origin www.cnblogs.com/Miracevin/p/11019351.html