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
",query(1,1,n,l,r)[gi()]);
}
return 0;
}