题目分析
这道题首先可以发现第三种操作和第二种操作都是很简单的,这里我就不多说了,但是对于加操作就有点需要特殊处理了 (a+b)3=a3+3a2b+3ab2+b3 很明显这样就可以推出来了,因为 a3,a2,a 都是已知的,因此可以处理了,注意先处理 (a+b)3 然后处理 (a+b)2 再处理 (a+b) 因为前面的需要用到后面的值,如果后面的更新了那么得到的结果就不对了。
除此之外还需要处理的就是3种操作的顺序,很明显对于第一种操作而言前2种操作可以直接忽略,但是对于第二种和第三种操作就不行了。我们用 add[o],mul[o],val[o] 分别代表三种操作的标记。
那么很明显如果val[o]有值应该首先处理,因为说明这个操作在第二种和第一种操作前面,不然的话mul[o]和add[o]都被设置为初始值了,然后处理第二种操作,如果在此之前已经有第一种操作,我们直接让add[o]乘以对应的值就可以了,不懂的可以想一想为什么。总之更新一定要注意顺序。
这道题程序挺复杂,因为手残错了n次,忘仔细思考再做。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int maxn = 1e5+10;
const int mod = 10007;
#define mid (L+R)/2
#define lson o<<1, L, mid
#define rson o<<1|1, mid+1, R
int sum1[maxn<<2], sum2[maxn<<2], sum3[maxn<<2];
int val[maxn<<2], add[maxn<<2], mul[maxn<<2];
void pushup(int o, int len){
if(len == 1) return ;
sum1[o] = (sum1[o<<1] + sum1[o<<1|1])%mod;
sum2[o] = (sum2[o<<1] + sum2[o<<1|1])%mod;
sum3[o] = (sum3[o<<1] + sum3[o<<1|1])%mod;
}
void pushdown(int o, int len){
if(len == 1) return ;
if(val[o] != -1){
val[o<<1] = val[o<<1|1] = val[o];
add[o<<1] = add[o<<1|1] = 0;
mul[o<<1] = mul[o<<1|1] = 1;
sum1[o<<1] = (len-(len>>1))%mod*val[o]%mod;
sum2[o<<1] = ((len-(len>>1))%mod)*(val[o]*val[o]%mod)%mod;
sum3[o<<1] = ((len-(len>>1))%mod)*((val[o]*val[o]%mod)*val[o]%mod)%mod;
sum1[o<<1|1] = ((len>>1)%mod)*val[o]%mod;
sum2[o<<1|1] = ((len>>1)%mod)*(val[o]*val[o]%mod)%mod;
sum3[o<<1|1] = ((len>>1)%mod)*((val[o]*val[o]%mod)*val[o]%mod)%mod;
val[o] = -1;
}
if(mul[o] != 1){
mul[o<<1] = (mul[o]*mul[o<<1])%mod, mul[o<<1|1] = (mul[o]*mul[o<<1|1])%mod;
add[o<<1] = add[o<<1]*mul[o]%mod, add[o<<1|1] = add[o<<1|1]*mul[o]%mod;
sum1[o<<1] = sum1[o<<1]*mul[o]%mod;
sum2[o<<1] = (sum2[o<<1]*mul[o]%mod)*mul[o]%mod;
sum3[o<<1] = ((sum3[o<<1]*mul[o]%mod)*mul[o]%mod)*mul[o]%mod;
sum1[o<<1|1] = sum1[o<<1|1]*mul[o]%mod;
sum2[o<<1|1] = (sum2[o<<1|1]*mul[o]%mod)*mul[o]%mod;
sum3[o<<1|1] = ((sum3[o<<1|1]*mul[o]%mod)*mul[o]%mod)*mul[o]%mod;
mul[o] = 1;
}
if(add[o]){
add[o<<1] = (add[o]+add[o<<1])%mod;
add[o<<1|1] = (add[o]+add[o<<1|1])%mod;
sum3[o<<1] = (sum3[o<<1] + (3*sum2[o<<1]*add[o])%mod + 3*(sum1[o<<1]*add[o]%mod)*add[o]%mod + ((add[o]*add[o]%mod)*add[o]%mod)*(len-(len>>1))%mod)%mod;
sum3[o<<1|1] = (sum3[o<<1|1] + (3*sum2[o<<1|1]*add[o])%mod + 3*(sum1[o<<1|1]*add[o]%mod)*add[o]%mod + ((add[o]*add[o]%mod)*add[o]%mod)*(len>>1)%mod)%mod;
sum2[o<<1] = (sum2[o<<1] + (2*sum1[o<<1]*add[o])%mod + (add[o]*add[o]%mod)*(len-(len>>1))%mod)%mod;
sum2[o<<1|1] = (sum2[o<<1|1] + (2*sum1[o<<1|1]*add[o])%mod + (add[o]*add[o]%mod)*(len>>1)%mod)%mod;
sum1[o<<1] = (sum1[o<<1] + add[o]*(len-(len>>1))%mod)%mod;
sum1[o<<1|1] = (sum1[o<<1|1] + add[o]*(len>>1)%mod)%mod;
add[o] = 0;
}
}
void build(int o,int L,int R){ //初始化
add[o] = 0, mul[o] = 1, val[o] = -1;
sum1[o] = sum2[o] = sum3[o] = 0;
if(L == R) return ;
build(lson);
build(rson);
}
void update(int o, int L, int R, int op, int l, int r, int c){
if(l <= L && R <= r){
c = c%mod;
if(op == 1){
add[o] =(add[o] + c)%mod;
sum3[o] = (sum3[o] + 3*sum2[o]%mod*c%mod + 3*sum1[o]%mod*c%mod*c%mod + c*c%mod*c%mod*(R-L+1)%mod)%mod;
sum2[o] = (sum2[o] + 2*sum1[o]%mod*c%mod + c*c%mod*(R-L+1)%mod)%mod;
sum1[o] = (sum1[o] + c*(R-L+1)%mod)%mod;
}
else if(op == 2){
add[o] = add[o]*c%mod;
mul[o] = mul[o]*c%mod;
sum1[o] = sum1[o]*c%mod;
sum2[o] = (sum2[o]*c%mod)*c%mod;
sum3[o] = ((sum3[o]*c%mod)*c%mod)*c%mod;
}
else if(op == 3){
val[o] = c, add[o] = 0, mul[o] = 1;
sum1[o] = ((R-L+1)%mod)*c%mod;
sum2[o] = ((R-L+1)%mod)*(c*c%mod)%mod;
sum3[o] = ((R-L+1)%mod)*((c*c%mod)*c%mod)%mod;
}
return ;
}
pushdown(o, R-L+1);
if(l <= mid) update(lson, op, l, r, c);
if(r > mid) update(rson, op, l, r, c);
pushup(o, R-L+1);
}
int query(int o, int L, int R, int l, int r, int c){
if(l <= L && R <= r){
if(c == 1) return sum1[o];
else if(c == 2) return sum2[o];
else return sum3[o];
}
pushdown(o, R-L+1);
int ret = 0;
if(l <= mid) ret = (ret + query(lson, l, r, c))%mod;
if(r > mid) ret = (ret + query(rson, l, r, c))%mod;
return ret;
}
int main(){
int n, m;
while(scanf("%d%d", &n, &m) != EOF){
if(!n && !m) break;
build(1, 1, n);
int op, x, y, c;
while(m--){
scanf("%d%d%d%d", &op, &x, &y, &c);
if(op == 4) printf("%d\n", query(1, 1, n, x, y, c)%mod);
else update(1, 1, n, op, x, y, c);
}
}
return 0;
}