【Description】
给定一个含有N个非负整数的序列,请写一个程序,支持以下两个操作:
1、Q l r 表示求l至r这一段所有数的和,结果对329701061取模
2、C l r 表示将l至r这一段中的每一个数变为其立方。
考场上想着打表找找取模之后的数有没有什么规律,忽然发现3次方一定次后会重复,接着发现每个数字3次方48次之后取模下来是一样的。
所以我们可以建一棵线段树,里面存一个结构体,分别维护当前为[0~47]次立方的和。
那么对于修改操作,
首先考虑区间的更新:如果包含了一个完整的区间,我们可以直接将当前的区间整体右移1位,即(x+1)%48,当然还要给lazy标记+1。
接着这样做了之后,覆盖它的区间[0~47]次立方的和,就可以直接加上当前区间的[0~47]次方,即永远默认当前区间的第一个位置为当前的值。
对于向下传递函数,即需要给左儿子与右儿子加上当前的lazy值,然后将左儿子与右儿子的区间右移当前的lazy值位。
最后查询的之后,只需要查询覆盖询问l,r的0次立方的和即可。
下附AC代码。
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<algorithm>
#define maxn 100005
#define lson (now<<1)
#define rson ((now<<1)|1)
#define mid ((nl+nr)>>1)
using namespace std;
typedef long long ll;
const ll mod=329701061;
struct nod
{
ll val[50];
nod(){memset(val,0,sizeof(val));}
}dat[maxn<<2];
int n;
char s[20];
ll temp[50];
ll a[maxn],lazy[maxn<<2];
nod bing(nod a,nod b)
{
nod ans;
for(int i=0;i<48;i++) ans.val[i]=(a.val[i]+b.val[i])%mod;
return ans;
}
void add(int now,int ad)
{
for(int i=0;i<48;i++) temp[i]=dat[now].val[i];
for(int i=0;i<48;i++) dat[now].val[i]=temp[(i+ad)%48];
}
void pushdown(int now)
{
if(lazy[now])
{
add(lson,lazy[now]);
add(rson,lazy[now]);
lazy[rson]+=lazy[now];lazy[rson]%=48;
lazy[lson]+=lazy[now];lazy[lson]%=48;
lazy[now]=0;
}
}
void pushup(int now)
{
dat[now]=bing(dat[lson],dat[rson]);
}
void build(int now,int nl,int nr)
{
if(nl==nr)
{
dat[now].val[0]=a[nl];
for(int i=1;i<48;i++)
dat[now].val[i]=(((dat[now].val[i-1]*dat[now].val[i-1])%mod)*dat[now].val[i-1])%mod;
return;
}
build(lson,nl,mid);
build(rson,mid+1,nr);
pushup(now);
}
void add(int ql,int qr,int now,int nl,int nr)
{
if(ql<=nl && nr<=qr)
{
lazy[now]++;lazy[now]%=48;
add(now,1);
return;
}
pushdown(now);
if(ql<=mid) add(ql,qr,lson,nl,mid);
if(mid<qr) add(ql,qr,rson,mid+1,nr);
pushup(now);
}
int query(int ql,int qr,int now,int nl,int nr)
{
if(ql<=nl && nr<=qr)
return dat[now].val[0];
pushdown(now);
int ans=0;
if(ql<=mid) ans+=query(ql,qr,lson,nl,mid),ans%=mod;
if(mid<qr) ans+=query(ql,qr,rson,mid+1,nr),ans%=mod;
pushup(now);
return ans;
}
int main()
{
freopen("query.in","r",stdin);
freopen("query.out","w",stdout);
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]);
build(1,1,n);
int _;
scanf("%d",&_);
while(_--)
{
int ql,qr;
scanf("%s%d%d",s,&ql,&qr);
if(s[0]=='C') add(ql,qr,1,1,n);
else printf("%d\n",query(ql,qr,1,1,n));
}
}