给定长度为n的初始序列a1,a2,⋯ ,an,接下来有q次操作:
- 对于操作1,输入l,r,val,d表示对区间[l,r]加一个首项为val,公差为d的等差数列。
- 对于操作2,输入l,r,m,表示询问区间[l,r]的和,并且对m取模。
第一行输入整数n (1≤n≤200000)。
接下来输入n个整数a1,a2⋯ ,ai (0≤ai≤109)。
接下来输入一个正整数q (1≤q≤2×10^5)。
接下来q行,每一行首先输入一个整数op∈{1,2}:
当op=1时,接下来输入l,r,val,d (1≤l,r≤n,0≤val,d≤10^9)表示第一种操作。
当op=2时,接下来输入l,r,m(1≤l,r≤n,3≤m≤25) 且m为素数,表示第二种操作。
输出描述:
对于每个操作2,输出询问的答案。示例1
输入
4 1 1 1 1 5 1 1 1 1 0 2 1 1 3 1 1 2 1 1 2 2 2 5 2 1 2 23输出
2 3 6
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5 + 7, mod = 3 * 5 * 7 * 11 * 13 * 17 * 19 * 23, Inv2 = mod - mod / 2;
typedef long long ll;
int n, q, a[maxn];
struct node
{
ll sum, val, d;
} t[maxn * 4];
ll cal(int l, int r, int val, int d)
{
ll cnt = r - l + 1;
ll ans = (1LL * val + (1LL * val + (cnt - 1) * (ll)d) % mod) % mod;
ans = (ans * cnt % mod * (ll)Inv2 % mod) % mod;
return ans;
}
void pushup(int rt)
{
t[rt].sum = (t[rt<<1].sum + t[rt<<1|1].sum) % mod;
}
void pushdown(int rt, int l, int r)
{
if(t[rt].val != 0 || t[rt].d != 0)
{
int mid = (l + r) >> 1;
t[rt<<1].sum = (t[rt<<1].sum + cal(l, mid, t[rt].val, t[rt].d)) % mod;
t[rt<<1].val = (t[rt<<1].val + t[rt].val) % mod;
t[rt<<1].d = (t[rt<<1].d + t[rt].d) % mod;
t[rt].val = (t[rt].val + (ll)(mid + 1 - l) * t[rt].d % mod) % mod;
t[rt<<1|1].sum = (t[rt<<1|1].sum + cal(mid + 1, r, t[rt].val, t[rt].d)) % mod;
t[rt<<1|1].val = ((t[rt<<1|1].val + t[rt].val) % mod);
t[rt<<1|1].d = (t[rt<<1|1].d + t[rt].d) % mod;
t[rt].val = 0;
t[rt].d = 0;
}
}
void build(int rt, int l, int r)
{
t[rt].val = t[rt].d = 0;
t[rt].sum = 0;
if(l == r)
{
t[rt].sum = a[l] % mod;
return;
}
int mid = (l + r) >> 1;
build(rt<<1, l, mid);
build(rt<<1|1, mid + 1, r);
pushup(rt);
}
void update(int rt, int l, int r, int L, int R, int val, int d)
{
if(L <= l && R >= r)
{
t[rt].sum = (t[rt].sum + cal(l, r, val, d)) % mod;
t[rt].val = (t[rt].val + val) % mod;
t[rt].d = (t[rt].d + d) % mod;
return ;
}
pushdown(rt, l, r);
int mid = (l + r) >> 1;
if(mid >= R) update(rt<<1, l, mid, L, R, val, d);
else if(mid < L) update(rt<<1|1, mid + 1, r, L, R, val, d);
else
{
update(rt<<1, l, mid, L, mid, val, d);
val = (1LL * val + 1LL * (mid + 1 - L) * d % mod) % mod;
update(rt<<1|1, mid + 1, r, mid + 1, R, val, d);
}/*
if(L<=mid)update(rt<<1,l,mid,L,R,val,d);
if(R>mid)update(rt<<1|1,mid+1,r,L,R,val,d);*/
pushup(rt);
}
ll query(int rt, int l, int r, int L, int R)
{
if(L <= l && R >= r)
{
return t[rt].sum;
}
pushdown(rt, l, r);
int mid = (l + r) >> 1;
ll ans = 0;
/* if(L <= mid) ans = (ans + query(rt<<1, l, mid, L, R)) % mod;
if(R > mid) ans = (ans + query(rt<<1|1, mid + 1, r, L, R)) % mod;*/
if(mid >= R) ans=(ans+query(rt<<1, l, mid, L, R))%mod;
else if(mid < L) ans=(ans+query(rt<<1|1, mid + 1, r, L, R))%mod;
else
{
ans=(ans+query(rt<<1, l, mid, L, mid)+query(rt<<1|1, mid + 1, r, mid + 1, R))%mod;
}
return ans;
}
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
build(1, 1, n);
scanf("%d", &q);
int op;
while (q--)
{
scanf("%d", &op);
if(op == 1)
{
int l, r, val, d;
scanf("%d%d%d%d", &l, &r, &val, &d);
update(1, 1, n, l, r, val, d);
}
else
{
int l, r, m;
scanf("%d%d%d", &l, &r, &m);
printf("%lld\n", query(1, 1, n, l, r) % m);
}
}
}