#if defined(_USE_PCH_)
#include "pch.hpp"
#else
#include <bits/stdc++.h>
#endif
#define RNG(V_, A_, B_, ...) for(int V_=(A_), V_##_END=(B_) __VA_OPT__(,) __VA_ARGS__; V_<=V_##_END; V_++)
#define IRNG(V_, A_, B_) for(int V_=(A_), V_##_END=(B_); V_>=V_##_END; V_--)
#ifdef _WIN32
#define long __int64
#endif
#if defined(_LOCAL_)
#undef assert
#define assert(expr) ({ if(!(expr)) asm("int3"); 0; })
#endif
using namespace std;
const long MOD1=998244353,MOD2=1e9+7;
const int MAXN=3100;
long qpow(long x,int p,int mod){
long ret=1;
for(; p; p>>=1,x=x*x%mod){
if(p&1) ret=ret*x%mod;
}
return ret;
}
struct Node{
int e[4]; long d[4]; // this.val=e[i].val+d[i]
} T[MAXN*MAXN];
int find(int u,int p){ return (T[u].e[0]==p ? 0 : T[u].e[1]==p ? 1 : T[u].e[2]==p ? 2 : 3); }
int turn(int u,int p,int d){ return T[u].e[(find(u,p)+d)%4]; }
tuple<int,int,long> walk(int u,int p,int c,long a,function<void(int,int,long)>* fn){
assert(u);
if(fn) (*fn)(u,p,a);
if(!c) return {u,p,a};
int t= p<=0 ? -p : (find(u,p)+2)%4;
return walk(T[u].e[t],u,c-1,a-T[u].d[t],fn);
}
void extract(int i,int j,int il,int jl,function<void(int,int,long)>* fn,int& dir){
auto [u1,p1,a1]=walk(1, -2,i,0,nullptr);
auto [u2,p2,a2]=walk(u1,-1,j,a1,nullptr);
int u=u2,p=p2; auto a=a2;
RNG(d,0,3){
dir=d;
tie(u,p,a)=walk(u,p,(d&1?jl:il),a,fn);
p=turn(u,p,1);
}
}
void add(int u,int p,long a){ T[u].d[find(u,p)]+=a; }
void add(int i,int j,int il,int jl,long a){
int dir;
function<void(int,int,long)> fn=[&dir,a](int u,int p,long){
auto b=(dir==0||dir==3?1:-1)*a;
p=turn(u,p,1);
add(u,p,b),add(p,u,-b);
};
extract(i,j,il,jl,&fn,dir);
}
void rotate(int i,int j,int l){
vector<tuple<int,int,long,long>> vec[4];
int dir;
function<void(int,int,long)> fn=[&dir,&vec](int u,int p,long a){
p=turn(u,p,1); auto b=a-T[u].d[find(u,p)];
vec[dir].push_back({u,p,a,b});
};
extract(i,j,l,l,&fn,dir);
RNG(d,0,3){
RNG(k,0,l-1){
auto [u1,p1,a1,b1]=vec[d][k]; auto [u2,p2,a2,b2]=vec[(d+1)%4][k];
T[u2].e[find(u2,p2)]=p1,T[p1].e[find(p1,u1)]=u2;
add(p1,u2,a2-a1),add(u2,p1,b1-b2);
}
}
}
int n,qn,id[MAXN][MAXN]; long val[MAXN][MAXN];
void build(){
int c=0;
RNG(i,0,n+1){
RNG(j,0,n+1){
id[i][j]=++c;
if(1<=i&&i<=n&&1<=j&&j<=n) val[i][j]=qpow(i+1,j,MOD1);
}
}
RNG(i,0,n+1){
RNG(j,0,n+1){
if(1<=i) T[id[i][j]].e[0]=id[i-1][j],T[id[i][j]].d[0]=val[i][j]-val[i-1][j];
if(j<=n) T[id[i][j]].e[1]=id[i][j+1],T[id[i][j]].d[1]=val[i][j]-val[i][j+1];
if(i<=n) T[id[i][j]].e[2]=id[i+1][j],T[id[i][j]].d[2]=val[i][j]-val[i+1][j];
if(1<=j) T[id[i][j]].e[3]=id[i][j-1],T[id[i][j]].d[3]=val[i][j]-val[i][j-1];
}
}
}
void extract(){
RNG(i,0,n+1){
int j=-1;
function<void(int,int,long)> fn=[i,&j](int u,int,long a){ ++j,id[i][j]=u,val[i][j]=a; };
walk(id[i][0],-1,n,0,&fn);
}
}
void check(){
extract();
RNG(i,0,n+1){
RNG(j,1,n){
if(1<=i) assert(T[id[i][j]].e[0]==id[i-1][j]&&T[id[i][j]].d[0]==val[i][j]-val[i-1][j]);
if(j<=n) assert(T[id[i][j]].e[1]==id[i][j+1]&&T[id[i][j]].d[1]==val[i][j]-val[i][j+1]);
if(i<=n) assert(T[id[i][j]].e[2]==id[i+1][j]&&T[id[i][j]].d[2]==val[i][j]-val[i+1][j]);
if(1<=j) assert(T[id[i][j]].e[3]==id[i][j-1]&&T[id[i][j]].d[3]==val[i][j]-val[i][j-1]);
}
}
}
int main(){
#if defined(_LOCAL_)
freopen("in","r",stdin);
// freopen("out","w",stdout);
#else
freopen("pack.in","r",stdin);
freopen("pack.out","w",stdout);
#endif
ios::sync_with_stdio(false),cin.tie(nullptr),cout.tie(nullptr);
cin>>n>>qn;
build();
check();
RNG(_,1,qn){
int op,x1,y1,x2,y2; long a; cin>>op>>x1>>y1>>x2>>y2;
if(op==1) rotate(x1,y1,x2-x1+1);
else cin>>a,add(x1,y1,x2-x1+1,y2-y1+1,a);
check();
}
extract();
long ans=0;
RNG(i,1,n){
long x=qpow(12345,(i-1)*n,MOD2);
RNG(j,1,n) x=x*12345%MOD2,(ans+=val[i][j]%MOD2*x)%=MOD2;
}
cout<<ans<<"\n";
}