bzoj 2962 序列操作

bzoj 2962 序列操作


神仙题啊orz。

一开始没看见\(c \leq 20\)感觉完全不可做

看见了就觉得可以直接维护这个东西

然后看修改

2号操作还好,但1号怎么搞?

找规律

\((a+x)(b+x)(c+x)(d+x)(e+x)=\)

\(abcde\)

\(x(abce+abde+acde+bcde+abcd)\)

\(x^2(abc+abd+abe+..)\)

\(x^3(ab+ac+ad+ae+bc+..)\)

\(x^4(a+b+c+d+e)\)

\(x^5\)

然后不明不白的推出\(A_i=\sum_{j=0}^{i}A_{i-j}C^{i}_{sz-j}x^{i-j}\)

就没有然后了

#include<bits/stdc++.h>
#define il inline
#define vd void
typedef long long ll;
il int gi(){
    int x=0,f=1;
    char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-')f=-1;
        ch=getchar();
    }
    while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
    return x*f;
}
#define mod 19940417
int a[50010];
int add[200010],inv[200010];
struct Node{
    int s[21];
    int&operator [](int x){return s[x];}
}A[200010];
il Node operator +(const Node&a,const Node&b){
    Node ret;
    for(int i=0;i<21;++i){
        ret[i]=0;
        for(int j=0;j<=i;++j)ret[i]+=1ll*a.s[j]*b.s[i-j]%mod;
        ret[i]%=mod;
    }
    return ret;
}
#define mid ((l+r)>>1)
il vd Mod(int&x){if(x>=mod)x-=mod;if(x<0)x+=mod;}
int C[50010][21];
il vd Add(int x,int l,int r,int c){
    for(int i=20;i;--i){
        int p=c;
        for(int j=i-1;~j;--j){
            if(r-l+1>=j)A[x][i]+=1ll*A[x][j]*p%mod*C[(r-l+1)-j][i-j]%mod;
            p=1ll*p*c%mod;
        }
        A[x][i]%=mod;
    }
    add[x]+=c;Mod(add[x]);
}
il vd Inv(int x){for(int i=1;i<20;i+=2)A[x][i]=mod-A[x][i],Mod(A[x][i]);inv[x]^=1,add[x]=mod-add[x],Mod(add[x]);}
il vd down(int x,int l,int r){
    if(inv[x])Inv(x<<1),Inv(x<<1|1),inv[x]=0;
    if(add[x])Add(x<<1,l,mid,add[x]),Add(x<<1|1,mid+1,r,add[x]),add[x]=0;
}
il vd build(int x,int l,int r){
    if(l==r){A[x][0]=1,A[x][1]=a[l];return;}
    build(x<<1,l,mid),build(x<<1|1,mid+1,r);
    A[x]=A[x<<1]+A[x<<1|1];
}
il vd update(int x,int l,int r,const int&L,const int&R,const int&d){
    if(L<=l&&r<=R)return Add(x,l,r,d);
    down(x,l,r);
    if(L<=mid)update(x<<1,l,mid,L,R,d);
    if(mid<R)update(x<<1|1,mid+1,r,L,R,d);
    A[x]=A[x<<1]+A[x<<1|1];
}
il vd update_r(int x,int l,int r,const int&L,const int&R){
    if(L<=l&&r<=R)return Inv(x);
    down(x,l,r);
    if(L<=mid)update_r(x<<1,l,mid,L,R);
    if(mid<R)update_r(x<<1|1,mid+1,r,L,R);
    A[x]=A[x<<1]+A[x<<1|1];
}
il Node query(int x,int l,int r,const int&L,const int&R){
    if(L<=l&&r<=R)return A[x];
    down(x,l,r);
    if(L<=mid)
        if(mid<R)return query(x<<1,l,mid,L,R)+query(x<<1|1,mid+1,r,L,R);
        else return query(x<<1,l,mid,L,R);
    else return query(x<<1|1,mid+1,r,L,R);
}
int main(){
#ifndef ONLINE_JUDGE
    freopen("2962.in","r",stdin);
    freopen("2962.out","w",stdout);
#endif
    C[0][0]=1;
    for(int i=1;i<50001;++i){
        C[i][0]=1;
        for(int j=1;j<=std::min(20,i);++j)C[i][j]=(C[i-1][j-1]+C[i-1][j])%mod;
    }
    int n=gi(),q=gi();
    for(int i=1;i<=n;++i)a[i]=gi();
    build(1,1,n);
    char opt[2];int l,r;
    while(q--){
        scanf("%s",opt);
        l=gi(),r=gi();
        if(opt[0]=='I')update(1,1,n,l,r,gi()%mod);
        else if(opt[0]=='R')update_r(1,1,n,l,r);
        else printf("%d\n",query(1,1,n,l,r)[gi()]);
    }
    return 0;
}
posted @ 2018-09-28 18:35  菜狗xzz  阅读(187)  评论(0编辑  收藏  举报