考虑每一位对答案的贡献, 在长度为 的序列中, 现在计算第 位的答案,
设 位 为 的数量为 , 为 的数量为 , ,
对答案的贡献为 .
根据 二项式定理 化第二项为: .
将第一项化为:
将括号拆开得到:
再使用 二项式定理 继续化简得到:
.
#include<bits/stdc++.h>
#define reg register
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 1e5 + 10;
const int mod = 998244353;
int N;
int M;
int A[maxn];
int pw[maxn];
int s[32][maxn];
int Ksm(int a, int b){ int s=1; while(b){if(b&1)s=1ll*s*a%mod;a=1ll*a*a%mod;b>>=1;} return s; }
void Work(){
int l = read(), r = read(), x = read(), Ans = 0;
for(reg int bit = 30; bit >= 0; bit --){
int n1 = s[bit][r] - s[bit][l-1], n0 = r-l+1-n1;
int res = (Ksm(x+1, n1) - Ksm((1-x+mod)%mod, n1) + mod) % mod;
res = 1ll*res*Ksm(2, mod-2) % mod;
res = 1ll*res * Ksm(x+1, n0) % mod;
res = 1ll*res*pw[bit] % mod;
Ans = (Ans + res) % mod;
}
printf("%d
", Ans);
}
int main(){
N = read(), M = read();
for(reg int i = 1; i <= N; i ++) A[i] = read();
pw[0] = 1; for(reg int i = 1; i <= 30; i ++) pw[i] = 2ll*pw[i-1] % mod;
for(reg int i = 0; i <= 30; i ++)
for(reg int j = 1; j <= N; j ++){
if(A[j] & (1 << i)) s[i][j] ++;
s[i][j] += s[i][j-1];
}
for(reg int i = 1; i <= M; i ++) Work();
return 0;
}