// An highlighted block
// Powered by Qiping Yan
#include<cstdio>
#include<unordered_map>
#include<queue>
using namespace std;
typedef unsigned long long uLL;
const int N = 1000000 + 10;
const uLL MOD = 2009731336725594113;
unordered_map<uLL,int> mp;
uLL U[5] = {314882150829468584,427197303358170108,1022292690726729920,1698479428772363217,2006101093849356424};
uLL f[40],arr[N][40];
int g[40][40];
int n,q;
struct segtree{
int L,R;
int s[40];
int res;
int tag;
void convert(int target){
int tmp[40];
for(int i = 1 ; i <= 32 ; i++ )
tmp[i] = s[g[i][target]];
for(int i = 1 ; i <= 32 ; i++ )
s[i] = tmp[i];
res = s[28];
if(tag == 0) tag = target;
else tag = g[tag][target];
}
};
segtree tree[N << 2];
uLL mul(uLL a,uLL b);
void get_convert();
void build(int p,int L,int R);
void pushdown(int p);
int ask(int p,int L,int R);
void change(int p,int L,int R,int k);
int main(){
get_convert();
scanf("%d%d",&n,&q);
for(int i = 1 ; i <= n ; i++ )
for(int j = 1 ; j <= 32 ; j++ ){
if(i == 1) arr[i][j] = f[j] % MOD;
else arr[i][j] = (f[j] + arr[i - 1][j]) % MOD;
}
build(1,1,n);
while(q--){
int L,R;
scanf("%d%d",&L,&R);
int ans = ask(1,L,R);
printf("%d\n", ans);
change(1,L,R,ans % 5);
}
return 0;
}
uLL mul(uLL a,uLL b){
uLL ret = 0;
while(b){
if(b & 1) ret = (ret + a) % MOD;
a = (a + a) % MOD;
b >>= 1;
}
return ret;
}
void get_convert(){
queue<uLL> que;
int cnt = 1;
for(int i = 0 ; i < 5 ; i++ ){
que.push(U[i]);
mp[U[i]] = cnt++;
}
while(!que.empty()){
uLL val = que.front(); que.pop();
f[mp[val]] = val;
for(int i = 0 ; i < 5 ; i++ ){
uLL tmp = mul(val,U[i]);
if(mp[tmp]) continue;
mp[tmp] = cnt++;
que.push(tmp);
}
}
for(int i = 1 ; i <= 32 ; i++ )
for(int j = i ; j <= 32 ; j++ )
g[i][j] = g[j][i] = mp[mul(f[i],f[j])];
return ;
}
void build(int p,int L,int R){
tree[p].L = L; tree[p].R = R;
if(L == R){
for(int i = 1 ; i <= 32 ; i++ )
tree[p].s[i] = arr[L][i] % 2019;
tree[p].res = tree[p].s[28];
tree[p].tag = 0;
return ;
}
int mid = (L + R) >> 1;
build(p * 2,L,mid);
build(p * 2 + 1,mid + 1,R);
for(int i = 1 ; i <= 32 ; i++ )
tree[p].s[i] = tree[p * 2].s[i] + tree[p * 2 + 1].s[i];
tree[p].res = tree[p].s[28];
tree[p].tag = 0;
return ;
}
void pushdown(int p){
if(!tree[p].tag) return ;
tree[2 * p].convert(tree[p].tag);
tree[2 * p + 1].convert(tree[p].tag);
tree[p].tag = 0;
return ;
}
int ask(int p,int L,int R){
if(tree[p].L >= L && tree[p].R <= R){
return tree[p].res;
}
pushdown(p);
int mid = (tree[p].L + tree[p].R) >> 1;
int res = 0;
if(mid >= L) res = ask(p * 2,L,R);
if(mid < R) res += ask(p * 2 + 1,L,R);
return res;
}
void change(int p,int L,int R,int k){
if(tree[p].L >= L && tree[p].R <= R){
tree[p].convert(k + 1);
return ;
}
pushdown(p);
int mid = (tree[p].L + tree[p].R) >> 1;
if(mid >= L) change(p * 2,L,R,k);
if(mid < R) change(p * 2 + 1,L,R,k);
for(int i = 1 ; i <= 32 ; i++ )
tree[p].s[i] = tree[p * 2].s[i] + tree[p * 2 + 1].s[i];
tree[p].res = tree[p].s[28];
return ;
}
参考博客
https://www.cnblogs.com/1625–H/p/12745977.html