Description
有一个长度为n的序列,有三个操作1.I a b c表示将[a,b]这一段区间的元素集体增加c,2.R a b表示将[a,b]区间内所有元素变成相反数,3.Q a b c表示询问[a,b]这一段区间中选择c个数相乘的所有方案的和mod 19940417的值。
Input
第一行两个数n,q表示序列长度和操作个数。
第二行n个非负整数,表示序列。
接下来q行每行输入一个操作I a b c或者 R a b或者Q a b c意义如题目描述。
Output
对于每个询问,输出选出c个数相乘的所有方案的和mod19940417的值。
Sample Input
5 5
1 2 3 4 5
I 2 3 1
Q 2 4 2
R 1 5
I 1 3 -1
Q 1 5 1
1 2 3 4 5
I 2 3 1
Q 2 4 2
R 1 5
I 1 3 -1
Q 1 5 1
Sample Output
40
19940397
题解:
线段树。懒得打题解,放张图吧。
19940397
代码无脑longlong
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<iostream>
using namespace std;
#define mod 19940417
#define ll long long
const ll N=60100;
ll n,q;
struct node{
ll sum[26];
}sa[N*4];
ll c[N][36],aa[N];
ll p1[N*4],d1[N*4];//标记相反数,加数
node update(node a,node b)
{
node c;
for(ll i=1;i<=20;i++) c.sum[i]=0;c.sum[0]=1;
for(ll i=1;i<=20;i++)
for(ll j=0;j<=i;j++)
(c.sum[i]+=(a.sum[j]*b.sum[i-j])%mod+mod)%=mod;
return c;
}
void built(ll k,ll l,ll r)
{
sa[k].sum[0]=1;
if(l==r){sa[k].sum[1]=aa[l];return;}
ll mid=(l+r)>>1;
built(k<<1,l,mid);built(k<<1|1,mid+1,r);
sa[k]=update(sa[k<<1],sa[k<<1|1]);
}
void get_mark(ll k,ll l,ll r,ll v,ll p)
{
ll f[30];ll len=r-l+1;
if(p)
{
for(ll i=1;i<=20;i++) if(i%2==1) sa[k].sum[i]=(mod-sa[k].sum[i])%mod;
p1[k]=!p1[k];d1[k]=(mod-d1[k])%mod;
}
if(v)
{
f[0]=1;for(ll i=1;i<=20;i++) f[i]=(f[i-1]*v+mod)%mod;
ll temp;
for(ll i=20;i>=1;i--)
{
temp=0;
for(ll j=0;j<=i;j++)
{
(temp+=((f[j]*sa[k].sum[i-j])%mod*c[len-i+j][j])%mod+mod)%=mod;
}
sa[k].sum[i]=temp;
}
}
d1[k]=(d1[k]+v+mod)%mod;
}
void pushdown(ll k,ll l,ll r)
{
ll mid=(l+r)>>1;
get_mark(k<<1,l,mid,d1[k],p1[k]);
get_mark(k<<1|1,mid+1,r,d1[k],p1[k]);
d1[k]=0;if (p1[k]) p1[k]=!p1[k];
}
void insert(ll k,ll l,ll r,ll l1,ll rr,long long v,ll pp){
ll mid=(l+r)>>1;
if (l1<=l&&r<=rr){get_mark(k,l,r,v,pp);return;}
if (p1[k]||d1[k]) pushdown(k,l,r);
if (l1<=mid) insert(k<<1,l,mid,l1,rr,v,pp);
if (rr>mid) insert(k<<1|1,mid+1,r,l1,rr,v,pp);
sa[k]=update(sa[k<<1],sa[k<<1|1]);
}
node query(ll k,ll l,ll r,ll l1,ll rr){
node ans,t1,t2;ll mid=(l+r)>>1;bool f1(0),f2(0);
if (l1<=l&&r<=rr) return sa[k];
if (p1[k]||d1[k]) pushdown(k,l,r);
if (l1<=mid) t1=query(k<<1,l,mid,l1,rr),f1=1;
if (rr>mid) t2=query(k<<1|1,mid+1,r,l1,rr),f2=1;
if (!f1) return t2;if (!f2) return t1;ans=update(t1,t2);return ans;
}
int main()
{
scanf("%lld%lld",&n,&q);
for(ll i=1;i<=n*4;i++) sa[i].sum[0]=1;c[0][0]=1;
for(ll i=1;i<=n;i++)
{
c[i][0]=1;c[i][i]=1;
for(ll j=1;j<=20;j++)
c[i][j]=(c[i-1][j-1]+c[i-1][j])%mod;
}
for(ll i=1;i<=n;i++)
scanf("%lld",&aa[i]);built(1,1,n);
char s[6];
ll a,b,c;
for(ll i=1;i<=q;i++)
{
scanf("%s",s);
if(s[0]=='I'){scanf("%lld%lld%lld",&a,&b,&c);insert(1,1,n,a,b,c,0);}
if(s[0]=='R'){scanf("%lld%lld",&a,&b);insert(1,1,n,a,b,0,1);}
if(s[0]=='Q'){scanf("%lld%lld%lld",&a,&b,&c);node yu;yu=query(1,1,n,a,b);printf("%lld\n",(yu.sum[c]+mod)%mod);}
}
}