#include<iostream>
#include<cstring>
using namespace std;
#define N 300005
#define MOD 998244353
long long trans[8][8],arr1[8][8],arr2[8][8],arr3[8][8],arr4[8][8],arr5[8][8],arr6[8][8];
struct seg{
long long times[8][8];
long long ju[8][8];
int l,r;
}tree[N];
void init(long long v){
memset(arr1,0,sizeof(arr1));
memset(arr2,0,sizeof(arr2));
memset(arr3,0,sizeof(arr3));
memset(arr4,0,sizeof(arr4));
memset(arr5,0,sizeof(arr5));
memset(arr6,0,sizeof(arr6));
for (int i=1;i<=4;i++){
arr1[i][i]=arr2[i][i]=arr3[i][i]=arr4[i][i]=arr5[i][i]=arr6[i][i]=1;
}
arr1[2][1]=1;
arr2[3][2]=1;
arr3[1][3]=1;
arr4[4][1]=v;
arr5[2][2]=v;
arr6[4][3]=v;
}
void pushdown(int root){
for (int i=1;i<=1;i++){
for (int j=1;j<=4;j++){
for (int k=1;k<=4;k++){
trans[i][j]=(trans[i][j]+tree[2*root].ju[i][k]*tree[root].times[k][j]%MOD)%MOD;
}
}
}
for (int j=1;j<=4;j++) tree[2*root].ju[1][j]=trans[1][j];
memset(trans,0,sizeof(trans));
for (int i=1;i<=1;i++){
for (int j=1;j<=4;j++){
for (int k=1;k<=4;k++){
trans[i][j]=(trans[i][j]+tree[2*root+1].ju[i][k]*tree[root].times[k][j]%MOD)%MOD;
}
}
}
for (int j=1;j<=4;j++) tree[2*root+1].ju[1][j]=trans[1][j];
memset(trans,0,sizeof(trans));
for (int i=1;i<=4;i++){
for (int j=1;j<=4;j++){
for (int k=1;k<=4;k++){
trans[i][j]=(trans[i][j]+tree[2*root].times[i][k]*tree[root].times[k][j]%MOD)%MOD;
}
}
}
for (int i=1;i<=4;i++){
for (int j=1;j<=4;j++) tree[root*2].times[i][j]=trans[i][j];
}
memset(trans,0,sizeof(trans));
for (int i=1;i<=4;i++){
for (int j=1;j<=4;j++){
for (int k=1;k<=4;k++){
trans[i][j]=(trans[i][j]+tree[2*root+1].times[i][k]*tree[root].times[k][j]%MOD)%MOD;
}
}
}
for (int i=1;i<=4;i++){
for (int j=1;j<=4;j++) tree[root*2+1].times[i][j]=trans[i][j];
}
for (int i=1;i<=4;i++){
for (int j=1;j<=4;j++){
if (i==j) tree[root].times[i][j]=1;
else tree[root].times[i][j]=0;
}
}
memset(trans,0,sizeof(trans));
}
void build(int root,int l,int r){
for (int i=1;i<=4;i++){
for (int j=1;j<=4;j++){
if (i==j) tree[root].times[i][j]=1;
else tree[root].times[i][j]=0;
}
}
tree[root].l=l,tree[root].r=r;
if(l==r){
for (int i=1;i<=3;i++){
scanf("%lld",&tree[root].ju[1][i]);
}
tree[root].ju[1][4]=1;
return;
}
int mid=(l+r)>>1;
build(root*2,l,mid);
build(root*2+1,mid+1,r);
for (int i=1;i<=3;i++){
tree[root].ju[1][i]=(tree[root*2].ju[1][i]+tree[2*root+1].ju[1][i])%MOD;
}
}
void fix(int root,int l,int r,long long arr[8][8]){
if (l<=tree[root].l && tree[root].r<=r){
memset(trans,0,sizeof(trans));
for (int i=1;i<=4;i++){
for (int j=1;j<=4;j++){
for (int k=1;k<=4;k++){
trans[i][j]=(trans[i][j]+tree[root].times[i][k]*arr[k][j]%MOD)%MOD;
}
}
}
for (int i=1;i<=4;i++){
for (int j=1;j<=4;j++) tree[root].times[i][j]=trans[i][j];
}
memset(trans,0,sizeof(trans));
for (int i=1;i<=1;i++){
for (int j=1;j<=4;j++){
for (int k=1;k<=4;k++){
trans[i][j]=(trans[i][j]+tree[root].ju[i][k]*arr[k][j]%MOD)%MOD;
}
}
}
for (int i=1;i<=4;i++) tree[root].ju[1][i]=trans[1][i];
return;
}
pushdown(root);
int mid=(tree[root].l+tree[root].r)>>1;
if (l<=mid) fix(root*2,l,r,arr);
if (r>=mid+1) fix(root*2+1,l,r,arr);
for (int i=1;i<=3;i++){
tree[root].ju[1][i]=(tree[root*2].ju[1][i]+tree[2*root+1].ju[1][i])%MOD;
}
}
seg query(int root,int l,int r){
if (l<=tree[root].l && tree[root].r<=r) return tree[root];
pushdown(root);
int mid=(tree[root].l+tree[root].r)>>1;
seg sum,a,b;
if (l<=mid){
a=query(root*2,l,r);
for (int i=1;i<=4;i++) sum.ju[1][i]+=a.ju[1][i];
}
if (r>=mid+1){
b=query(root*2+1,l,r);
for (int i=1;i<=4;i++) sum.ju[1][i]+=b.ju[1][i];
}
return sum;
}
int main(){
int n;
scanf("%d",&n);
build(1,1,n);
int m;
scanf("%d",&m);
while (m--){
int op,l,r;
long long v;
scanf("%d%d%d",&op,&l,&r);
if (op==1){
init(0);
fix(1,l,r,arr1);
}
if (op==2){
init(0);
fix(1,l,r,arr2);
}
if (op==3){
init(0);
fix(1,l,r,arr3);
}
if (op==4){
scanf("%lld",&v);
init(v);
fix(1,l,r,arr4);
}
if (op==5){
scanf("%lld",&v);
init(v);
fix(1,l,r,arr5);
}
if (op==6){
scanf("%lld",&v);
init(v);
fix(1,l,r,arr6);
}
if (op==7){
seg ans=query(1,l,r);
printf("%lld %lld %lld\n",ans.ju[1][1]%MOD,ans.ju[1][2]%MOD,ans.ju[1][3]%MOD);
}
}
return 0;
}