#include <bits/stdc++.h>
using namespace std;

using ll=long long;
//#define int ll

#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define a first
#define b second
#define bg begin()
#define ed end()
#define all(x) x.bg,x.ed
#define si(x) int(x.size())
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif

template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}

template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;

using pi=pair<int,int>;
using vi=vc<int>;

template<class t,class u>
ostream& operator<<(ostream& os,const pair<t,u>& p){
	return os<<"{"<<p.a<<","<<p.b<<"}";
}

template<class t> ostream& operator<<(ostream& os,const vc<t>& v){
	os<<"{";
	for(auto e:v)os<<e<<",";
	return os<<"}";
}

#define mp make_pair
#define mt make_tuple
#define one(x) memset(x,-1,sizeof(x))
#define zero(x) memset(x,0,sizeof(x))
#ifdef LOCAL
void dmpr(ostream&os){os<<endl;}
template<class T,class... Args>
void dmpr(ostream&os,const T&t,const Args&... args){
	os<<t<<" ";
	dmpr(os,args...);
}
#define dmp2(...) dmpr(cerr,__LINE__,##__VA_ARGS__)
#else
#define dmp2(...) void(0)
#endif

using uint=unsigned;
using ull=unsigned long long;

template<class t,size_t n>
ostream& operator<<(ostream&os,const array<t,n>&a){
	return os<<vc<t>(all(a));
}

template<int i,class T>
void print_tuple(ostream&,const T&){
}

template<int i,class T,class H,class ...Args>
void print_tuple(ostream&os,const T&t){
	if(i)os<<",";
	os<<get<i>(t);
	print_tuple<i+1,T,Args...>(os,t);
}

template<class ...Args>
ostream& operator<<(ostream&os,const tuple<Args...>&t){
	os<<"{";
	print_tuple<0,tuple<Args...>,Args...>(os,t);
	return os<<"}";
}

template<class t>
void print(t x,int suc=1){
	cout<<x;
	if(suc==1)
		cout<<"\n";
	if(suc==2)
		cout<<" ";
}

ll read(){
	ll i;
	cin>>i;
	return i;
}

vi readvi(int n,int off=0){
	vi v(n);
	rep(i,n)v[i]=read()+off;
	return v;
}

template<class T>
void print(const vector<T>&v,int suc=1){
	rep(i,v.size())
		print(v[i],i==int(v.size())-1?suc:2);
}

string readString(){
	string s;
	cin>>s;
	return s;
}

template<class T>
T sq(const T& t){
	return t*t;
}

//#define CAPITAL
void yes(bool ex=true){
	#ifdef CAPITAL
	cout<<"YES"<<"\n";
	#else
	cout<<"Yes"<<"\n";
	#endif
	if(ex)exit(0);
}
void no(bool ex=true){
	#ifdef CAPITAL
	cout<<"NO"<<"\n";
	#else
	cout<<"No"<<"\n";
	#endif
	if(ex)exit(0);
}
void possible(bool ex=true){
	#ifdef CAPITAL
	cout<<"POSSIBLE"<<"\n";
	#else
	cout<<"Possible"<<"\n";
	#endif
	if(ex)exit(0);
}
void impossible(bool ex=true){
	#ifdef CAPITAL
	cout<<"IMPOSSIBLE"<<"\n";
	#else
	cout<<"Impossible"<<"\n";
	#endif
	if(ex)exit(0);
}

constexpr ll ten(int n){
	return n==0?1:ten(n-1)*10;
}

const ll infLL=LLONG_MAX/3;

#ifdef int
const int inf=infLL;
#else
const int inf=INT_MAX/2-100;
#endif

int topbit(signed t){
	return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
	return t==0?-1:63-__builtin_clzll(t);
}
int botbit(signed a){
	return a==0?32:__builtin_ctz(a);
}
int botbit(ll a){
	return a==0?64:__builtin_ctzll(a);
}
int popcount(signed t){
	return __builtin_popcount(t);
}
int popcount(ll t){
	return __builtin_popcountll(t);
}
bool ispow2(int i){
	return i&&(i&-i)==i;
}
int mask(int i){
	return (int(1)<<i)-1;
}

bool inc(int a,int b,int c){
	return a<=b&&b<=c;
}

template<class t> void mkuni(vc<t>&v){
	sort(all(v));
	v.erase(unique(all(v)),v.ed);
}

ll rand_int(ll l, ll r) { //[l, r]
	#ifdef LOCAL
	static mt19937_64 gen;
	#else
    static random_device rd;
    static mt19937_64 gen(rd());
    #endif
    return uniform_int_distribution<ll>(l, r)(gen);
}

template<class t>
int lwb(const vc<t>&v,const t&a){
	return lower_bound(all(v),a)-v.bg;
}

using uint=unsigned;
using ull=unsigned long long;

struct modinfo{uint mod,root;};
template<modinfo const&ref>
struct modular{
	static constexpr uint const &mod=ref.mod;
	static modular root(){return modular(ref.root);}
	uint v;
	//modular(initializer_list<uint>ls):v(*ls.bg){}
	modular(ll vv=0){s(vv%mod+mod);}
	modular& s(uint vv){
		v=vv<mod?vv:vv-mod;
		return *this;
	}
	modular operator-()const{return modular()-*this;}
	modular& operator+=(const modular&rhs){return s(v+rhs.v);}
	modular&operator-=(const modular&rhs){return s(v+mod-rhs.v);}
	modular&operator*=(const modular&rhs){
		v=ull(v)*rhs.v%mod;
		return *this;
	}
	modular&operator/=(const modular&rhs){return *this*=rhs.inv();}
	modular operator+(const modular&rhs)const{return modular(*this)+=rhs;}
	modular operator-(const modular&rhs)const{return modular(*this)-=rhs;}
	modular operator*(const modular&rhs)const{return modular(*this)*=rhs;}
	modular operator/(const modular&rhs)const{return modular(*this)/=rhs;}
	modular pow(int n)const{
		modular res(1),x(*this);
		while(n){
			if(n&1)res*=x;
			x*=x;
			n>>=1;
		}
		return res;
	}
	modular inv()const{return pow(mod-2);}
	/*modular inv()const{
		int x,y;
		int g=extgcd(v,mod,x,y);
		assert(g==1);
		if(x<0)x+=mod;
		return modular(x);
	}*/
	friend modular operator+(int x,const modular&y){
		return modular(x)+y;
	}
	friend modular operator-(int x,const modular&y){
		return modular(x)-y;
	}
	friend modular operator*(int x,const modular&y){
		return modular(x)*y;
	}
	friend modular operator/(int x,const modular&y){
		return modular(x)/y;
	}
	friend ostream& operator<<(ostream&os,const modular&m){
		return os<<m.v;
	}
	friend istream& operator>>(istream&is,modular&m){
		ll x;is>>x;
		m=modular(x);
		return is;
	}
	bool operator<(const modular&r)const{return v<r.v;}
	bool operator==(const modular&r)const{return v==r.v;}
	bool operator!=(const modular&r)const{return v!=r.v;}
	explicit operator bool()const{
		return v;
	}
};

constexpr modinfo base{998244353,3};
//constexpr modinfo base{1000000007,0};
using mint=modular<base>;

const int vmax=(1<<21)+10;
mint fact[vmax],finv[vmax],invs[vmax];
void initfact(){
	fact[0]=1;
	rng(i,1,vmax){
		fact[i]=fact[i-1]*i;
	}
	finv[vmax-1]=fact[vmax-1].inv();
	for(int i=vmax-2;i>=0;i--){
		finv[i]=finv[i+1]*(i+1);
	}
	for(int i=vmax-1;i>=1;i--){
		invs[i]=finv[i]*fact[i-1];
	}
}
mint choose(int n,int k){
	return fact[n]*finv[n-k]*finv[k];
}
mint binom(int a,int b){
	return fact[a+b]*finv[a]*finv[b];
}
mint catalan(int n){
	return binom(n,n)-(n-1>=0?binom(n-1,n+1):0);
}

vc<mint> mod_f(vc<mint> x,const vc<mint>&f){
	int k=si(f);
	gnr(i,k-1,si(x)){
		mint w=x[i]/f[k-1];
		rep(p,k-1)x[i-(k-1)+p]-=w*f[p];
	}
	x.resize(k-1);
	return x;
}

vc<mint> mult_mod_f(const vc<mint>&x,const vc<mint>&y,const vc<mint>&f){
	int n=si(x),m=si(y);
	vc<mint> res(n+m-1);
	rep(i,n)rep(j,m)res[i+j]+=x[i]*y[j];
	return mod_f(res,f);
}

vc<mint> pow_mod_f(vc<mint> x,int n,const vc<mint>&f){
	vc<mint> res{1};
	while(n){
		if(n&1)res=mult_mod_f(res,x,f);
		x=mult_mod_f(x,x,f);
		n>>=1;
	}
	return res;
}

// for all valid i, sum_j a_{i+j}*res_j = 0
// x^n % res で n 項目が求まる
// 多項式の向きに注意
vc<mint> berlekamp_massey(const vc<mint>& a){
	vc<mint> b{1},c{0};
	mint d=1;
	rep(i,a.size()){
		int n=b.size();
		mint w=0;
		rep(j,n)
			w+=a[i-(n-1)+j]*b[j];
		c.pb(0);
		if(!w.v)continue;
		int m=c.size();
		mint e=-w/d;
		if(m>n){
			auto tmp=b;
			b.insert(b.bg,m-n,0);
			rep(j,m)
				b[j]+=e*c[j];
			c=tmp;
			d=w;
		}else{
			rep(j,m)
				b[n-m+j]+=e*c[j];
		}
	}
	return b;
}

mint get_kth(const vc<mint>&a,int k){
	auto p=berlekamp_massey(a);
	if(si(p)==1)return 0;
	auto q=pow_mod_f({0,1},k,p);
	mint res=0;
	rep(i,si(q))res+=a[i]*q[i];
	return res;
}

//(-pi,0](0,pi]
int argtype(pi a){
	if(a.b==0)return a.a<0?1:0;
	return a.b<0?0:1;
}
bool argless(pi a,pi b){
	int at=argtype(a),bt=argtype(b);
	if(at!=bt)return at<bt;
	return a.a*b.b-a.b*b.a>0;
};

mint interpolate(const vc<mint>&a,mint x){
	int n=si(a);
	if(inc(0,x.v,n-1))return a[x.v];
	mint w=1;
	rep(i,n)w*=x-i;
	mint res;
	rep(i,n)res+=w/(x-i)*a[i]*finv[i]*finv[n-1-i]*((n-1-i)%2?-1:1);
	return res;
}

const int mmax=185;
//const int mmax=15;

mint dp[mmax][mmax];
mint buf[mmax][mmax];

signed main(){
	cin.tie(0);
	ios::sync_with_stdio(0);
	cout<<fixed<<setprecision(20);

	initfact();

	int n,m;cin>>n>>m;
	vc<pi> xy;
	rep(i,n){
		int x,y;cin>>x>>y;
		xy.eb(x,y);
	}
	sort(all(xy),argless);
	dmp(xy);
	int L=mmax-5;
	rep(w,L)rng(h,w,w+2){
		rep(sx,w+1)rng(sy,h,h+1){
			zero(dp);
			dp[sx][sy]=1;
			for(auto z:xy){
				rep(xx,w+1)rep(yy,h+1){
					int x=z.a<0?w-xx:xx;
					int y=z.b<0?h-yy:yy;
					int p=x+z.a,q=y+z.b;
					if(inc(0,p,w)&&inc(0,q,h)){
						dp[p][q]+=dp[x][y];
					}
				}
			}
			buf[w][h]+=dp[sx][sy]-1;
		}
	}
	vc<mint> val(L);
	//rng(i,1,L)val[i]=buf[i][i]-buf[i][i-1]*2+buf[i-1][i-1];
	rng(i,1,L)val[i]=buf[i][i]-buf[i-1][i];

	cout<<get_kth(val,m)<<endl;
}


//~ while (clock()<=69*CLOCKS_PER_SEC)
//~ #pragma comment(linker, "/stack:200000000")
#pragma GCC optimize("O3")
//~ #pragma GCC target ("avx2")
//~ #pragma GCC optimize("Ofast")
//~ #pragma GCC target("sse,sse2,sse3,ssse3,sse4,popcnt,abm,mmx,avx,tune=native")
//~ #pragma GCC optimize("unroll-loops")
#include <bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>

using namespace __gnu_pbds;
using namespace std;

template <typename T>
using ordered_set =
    tree<T, null_type, less<T>, rb_tree_tag, tree_order_statistics_node_update>;

#define sim template < class c
#define ris return * this
#define dor > debug & operator <<
#define eni(x) sim > typename \
  enable_if<sizeof dud<c>(0) x 1, debug&>::type operator<<(c i) {
sim > struct rge { c b, e; };
sim > rge<c> range(c i, c j) { return rge<c>{i, j}; }
sim > auto dud(c* x) -> decltype(cerr << *x, 0);
sim > char dud(...);
struct debug {
#ifdef LOCAL
~debug() { cerr << endl; }
eni(!=) cerr << boolalpha << i; ris; }
eni(==) ris << range(begin(i), end(i)); }
sim, class b dor(pair < b, c > d) {
  ris << "(" << d.first << ", " << d.second << ")";
}
sim dor(rge<c> d) {
  *this << "[";
  for (auto it = d.b; it != d.e; ++it)
    *this << ", " + 2 * (it == d.b) << *it;
  ris << "]";
}
#else
sim dor(const c&) { ris; }
#endif
};
#define imie(...) " [" << #__VA_ARGS__ ": " << (__VA_ARGS__) << "] "

#define shandom_ruffle random_shuffle

using ll=long long;
using pii=pair<int,int>;
using pll=pair<ll,ll>;
using vi=vector<int>;
using vll=vector<ll>;
const int nax=1000*1007;
const ll mod=998244353;

void add_self(int & a, int b) { a += b; if(a >= mod) a -= mod; }
void sub_self(int & a, int b) { a -= b; if(a < 0) a += mod; }
int mul(int a, int b) { return (ll) a * b % mod; }
int my_pow(int a, int b) {
	int r = 1;
	while(b) {
		if(b % 2) r = mul(r, a);
		a = mul(a, a);
		b /= 2;
	}
	return r;
}
int my_inv(int a) { return my_pow(a, mod - 2); }
struct Massey {
	vector<int> start, coef; // 3 optional lines
	vector<vector<int>> powers;
	int memo_inv;
	// Start here and write the next ~25 lines until "STOP"
	int L; // L == coef.size() <= start.size()
	Massey(vector<int> in) { // O(N^2)
		L = 0;
		const int N = in.size();
		vector<int> C{1}, B{1};
		for(int n = 0; n < N; ++n) {
			assert(0 <= in[n] && in[n] < mod); // invalid input
			B.insert(B.begin(), 0);
			int d = 0;
			for(int i = 0; i <= L; ++i)
				add_self(d, mul(C[i], in[n-i]));
			if(d == 0) continue;
			vector<int> T = C;
			C.resize(max(B.size(), C.size()));
			for(int i = 0; i < (int) B.size(); ++i)
				sub_self(C[i], mul(d, B[i]));
			if(2 * L <= n) {
				L = n + 1 - L;
				B = T;
				d = my_inv(d);
				for(int & x : B) x = mul(x, d);
			}
		}
		cerr << "L = " << L << "\n";
		assert(2 * L <= N - 2); // NO RELATION FOUND :(
		// === STOP ===
		for(int i = 1; i < (int) C.size(); ++i)
			coef.push_back((mod - C[i]) % mod);
		assert((int) coef.size() == L);
		for(int i = 0; i < L; ++i)
			start.push_back(in[i]);
		while(!coef.empty() && !coef.back()) { coef.pop_back(); --L; }
		if(!coef.empty()) memo_inv = my_inv(coef.back());
		powers.push_back(coef);
	}
	vector<int> mul_cut(vector<int> a, vector<int> b) {
		vector<int> r(2 * L - 1);
		for(int i = 0; i < L; ++i)
			for(int j = 0; j < L; ++j)
				add_self(r[i+j], mul(a[i], b[j]));
		while((int) r.size() > L) {
			int value = mul(r.back(), memo_inv); // div(r.back(), coef.back());
			const int X = r.size();
			add_self(r[X-L-1], value);
			for(int i = 0; i < L; ++i)
				sub_self(r[X-L+i], mul(value, coef[i]));
			assert(r.back() == 0);
			r.pop_back();
		}
		return r;
	}
	int get(ll k) { // O(L^2 * log(k))
		if(k < (int) start.size()) return start[k];
		if(L == 0) return 0;
		k -= start.size();
		vector<int> vec = coef;
		for(int i = 0; (1LL << i) <= k; ++i) {
			if(i == (int) powers.size())
				powers.push_back(mul_cut(powers.back(), powers.back()));
			if(k & (1LL << i))
				vec = mul_cut(vec, powers[i]);
		}
		int total = 0;
		for(int i = 0; i < L; ++i)
			add_self(total, mul(vec[i], start[(int)start.size()-1-i]));
		return total;
	}
};

int n;
ll m;

pii tab[nax];

ll ile[nax];

int n1, n2;

const int d=1000;

vector <pii> mapa[2*d+7][2*d+7];

void rek1(int v, int x, int y, int sx, int sy)
{
	if (abs(x)>d || abs(y)>d || sx>d || sy>d)
		return;
	if (v==n1)
	{
		mapa[x+d][y+d].push_back({sx, sy});
		return;
	}
	for (int i=0; i<=d; i++)
	{
		rek1(v-1, x+tab[v].first*i, y+tab[v].second*i, sx+max(tab[v].first, 0)*i, sy+max(tab[v].second, 0)*i);
	}
}

void rek2(int v, int x, int y, int sx, int sy)
{
	if (abs(x)>d || abs(y)>d || sx>d || sy>d)
		return;
	if (v==n1+1)
	{
		for (pii i : mapa[-x+d][-y+d])
		{
			ile[max(sx+i.first, sy+i.second)]++;
		}
		//~ mapa[x+d][y+d].push_back({sx, sy});
		return;
	}
	for (int i=0; i<=d; i++)
	{
		rek2(v+1, x+tab[v].first*i, y+tab[v].second*i, sx+max(tab[v].first, 0)*i, sy+max(tab[v].second, 0)*i);
	}
}

int main()
{
	scanf("%d%lld", &n, &m);
	for (int i=1; i<=n; i++)
		scanf("%d%d", &tab[i].first, &tab[i].second);
	n1=(n+1)/2;
	rek1(n, 0, 0, 0, 0);
	rek2(1, 0, 0, 0, 0);
	vi wez;
	ll s=0;
	for (int i=0; i<=d; i++)
	{
		s+=ile[i];
		s%=mod;
		wez.push_back(s);
	}
	debug() << wez;
	Massey mas=Massey(wez);
	printf("%lld\n", (mas.get(m)-1+mod)%mod);
	return 0;
}


// by ξ
// program sky  :)

#include <cstdio>
#include <cstring>
#include <algorithm>

#define elif else if
#define For(i,l,r) for(int _r=r,i=l;i<=_r;++i)
#define rep(i,l,r) for(int _r=r,i=l;i<_r;++i)
#define dto(i,r,l) for(int _l=l,i=r;i>=_l;--i)

using namespace std;

inline void hello(){
	//freopen("painting.in","r",stdin);
	//freopen("painting.out","w",stdout);
}

int n,K,mo,M,dp[2][201][16],he[55],binom[55][55],tr[55][55][201],kua[55],way[55][5];

struct Edge{
	int v,k,con,nxt;
}Ed[5000];

#define cnt(x) (__builtin_popcount(x))

inline void inc(int &x,int y){
	if((x+=y)>=mo)x-=mo;
}

inline void Add(int u,int v,int k,int con){
	Ed[++M]=(Edge){v,k,con,he[u]};he[u]=M;
}

int main(){
// say hello
	hello();
	scanf("%d%d%d",&n,&K,&mo);

	For(i,0,22){
		*binom[i]=1;
		For(j,1,i)
			binom[i][j]=(binom[i-1][j-1]+binom[i-1][j])%mo;
	}
	int lim=1<<4;--lim;

	kua[0]=4;
	kua[1]=kua[2]=kua[4]=kua[8]=2;
	kua[3]=kua[6]=kua[9]=kua[12]=1;

	way[0][0]=1;
	way[1][1]=way[2][1]=way[4][1]=way[8][1]=1;
	way[5][2]=way[10][2]=1;
	way[3][1]=way[6][1]=way[9][1]=way[12][1]=1;
	way[3][2]=way[6][2]=way[9][2]=way[12][2]=1;
	way[7][3]=way[11][3]=way[13][3]=way[14][3]=1;
	way[7][2]=way[11][2]=way[13][2]=way[14][2]=2;
	way[15][4]=1;
	way[15][2]=2;
	way[15][3]=4;

	For(i,0,lim)
	For(j,0,lim)if((j&i)==0){
		int k=i|j;
		For(p,0,kua[k]){
			int _=(4-cnt(k))*3-p*2;
			For(q,0,_)
				For(cn,0,4)if(way[j][cn])
				inc(tr[i][k][cn+p+q],1ll*binom[kua[k]][p]*binom[_][q]%mo*way[j][cn]%mo);
		}
	}

	For(i,0,lim)dto(k,12,0)For(j,0,lim)
		if(tr[i][j][k])Add(i,j,k,tr[i][j][k]);

	dp[n+1&1][0][0]=1;

	dto(i,n+1,2){
		int p=i&1,q=p^1;
		memset(dp[q],0,sizeof dp[q]);
		For(k,0,K)
		For(mask,0,lim)if(dp[p][k][mask])
			for(int e=he[mask];e;e=Ed[e].nxt){
				int kk=k+Ed[e].k;
				if(kk>K)break;
				inc(dp[q][kk][Ed[e].v],1ll*dp[p][k][mask]*Ed[e].con%mo);
			}
	}

	dto(i,lim,0)
	For(j,0,lim)if(j>i && (i&j)==i)
	For(k,0,4)
	inc(way[j][k],way[i][k]);

	int res=0;
	For(k,max(K-4,0),K)
	For(mask,0,lim)if(dp[1][k][mask])
		inc(res,1ll*dp[1][k][mask]*way[lim-mask][K-k]%mo);

	For(i,2,K)res=1ll*res*i%mo;
	printf("%d\n",res%mo);
// never say goodbye
}


#include <cstdlib>
#include <cstring>
#include <memory>
#include <cstdio>
#include <fstream>
#include <iostream>
#include <cmath>
#include <string>
#include <sstream>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <algorithm>
using namespace std;

typedef signed long long ll;

#undef _P
#define _P(...) (void)printf(__VA_ARGS__)

#define FOR(x,to) for(x=0;x<to;x++)
#define ITR(x,c) for(__typeof(c.begin()) x=c.begin();x!=c.end();x++)
#define ZERO(a) memset(a,0,sizeof(a))
void _fill_int(int* p,int val,int rep) {int i;  FOR(i,rep) p[i]=val;}
void _fill_ll(ll* p,ll val,int rep) {int i; FOR(i,rep) p[i]=val;}
#define MINUS(a) _fill_int((int*)a,-1,sizeof(a)/4)
#define MINUSL(a) _fill_ll((ll*)a,-1LL,sizeof(a)/8)
ll GETi() { ll i;scanf("%lld",&i); return i;}
//-------------------------------------------------------

int N,K;
ll mo=1000000007;
ll dpdp[105][105][16];
const int CN=20;
ll C[CN][CN];

ll dodp(int level,int num,int mask) {
    int ma,i,j,k[5],l;
    if(num==0) return 1;
    if(num<0 || mask==0) return 0;
    if(dpdp[level][num][mask]!=-1) return dpdp[level][num][mask];
    /*
    if(mask==13 || mask==11 || mask==14) return dpdp[level][num][mask]=dodp(level,num,7); //used 1
    if(mask==9|| mask==6 || mask==12) return dpdp[level][num][mask]=dodp(level,num,3); //used 2
    if(mask==10) return dpdp[level][num][mask]=dodp(level,num,5); //used 2
    if(mask==2|| mask==4 || mask==8) return dpdp[level][num][mask]=dodp(level,num,1); //used 3
    */

    ll ret=0;
    FOR(ma,16) {
        if((mask & ma)!=ma) continue;

        //get whole block
        int bi=__builtin_popcount(ma);
        k[0]=k[1]=k[2]=k[3]=k[4]=0;
        k[bi]=1;
        if(bi==2 && (ma!=5) && (ma!=10)) k[1]++;
        if(bi==3) k[2]+=2;
        if(bi==4) k[2]+=2,k[3]+=4;

        // get boarder
        if(level>0) {
            int ma2=mask^ma;
            if(ma2==13 || ma2==11 || ma2==14) ma2=7;
            if(ma2==9 || ma2==6 || ma2==12) ma2=3;
            if(ma2==10) ma2=5;
            if(ma2==2 || ma2==4 || ma2==8) ma2=1;

            int x,y;
            FOR(l,5){
                if(k[l]==0) continue;
                if(num-l<0) continue;
                if(ma2==0) x=0,y=0;
                else if(ma2==1) x=3,y=0;
                else if(ma2==5) x=6,y=0;
                else if(ma2==3) x=6,y=1;
                else if(ma2==7) x=9,y=2;
                else if(ma2==15) x=12,y=4;
                FOR(i,y+1) FOR(j,x-i*2+1) ret += dodp(level-1,num-l-(i+j),ma2) * ((k[l]* C[y][i] * C[x-i*2][j])%mo);
            }
        }
        else {
            FOR(l,5) ret += (num==l) * k[l];
        }
    }

    return dpdp[level][num][mask]=(ret%=mo);
}

void solve() {
    int f,i,j,k,l, x,y;

    cin>>N>>K;
    FOR(x,CN) C[x][0]=C[x][x]=1;
    for(i=1;i<CN;i++) for(j=1;j<i;j++) C[i][j]=(C[i-1][j-1]+C[i-1][j])%mo;
    MINUSL(dpdp);

    ll ret=dodp(N,K,15);
    FOR(i,K) ret=(ret*(i+1))%mo;
    cout << ret << endl;
}

int main(int argc,char** argv){
    if(argc>1) freopen(argv[1], "r", stdin);
    solve();
    return 0;
}


/*
 * temp.cpp
 *
 *  Created on: 2012-7-18
 *      Author: BSBandme
 */
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <fstream>
#include <string.h>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <cassert>
#include <list>
#include <iomanip>
#include <math.h>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <climits>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <time.h>

using namespace std;

#define mpr make_pair
typedef unsigned long long ull;
typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <double, double> pdd;
typedef vector <int> vi;
typedef vector <ll> vll;
typedef vector <double> vd;
typedef vector <string> vs;
typedef map <string, int> mpsi;
typedef map <double, int> mpdi;
typedef map <int, int> mpii;

const double pi = acos(0.0) * 2.0;
const double eps = 1e-12;
const int step[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};

template <class T> inline T abs1(T a) {return a < 0 ? -a : a;}
template <class T> inline T max1(T a, T b, T c = -1234567, T d = -1234567) {
	T ans =  a > b ? a : b;
	if(c != -1234567) ans = max1(ans, c);
	if(d != -1234567) ans = max1(ans, d);
	return ans;
}
template <class T> inline T min1(T a, T b, T c = -1234567, T d = -1234567) {
	T ans = a < b ? a : b;
	if(c != -1234567) ans = min(ans, c);
	if(d != -1234567) ans = min(ans, d);
	return ans;
}
template <class T> inline T gcd1(T a, T b) {
	if(a < b) swap(a, b);
	if(a % b == 0) return b;
	return gcd1(b, a % b);
}
template <class T> inline T lb(T num) {return num & (-num); }
inline int jud(double a, double b){
	if(abs(a) < eps && abs(b) < eps) return 0;
	else if(abs1(a - b) / abs1(a) < eps) return 0;
	if(a < b) return -1;
	return 1;
}
template <typename t>
inline int jud(t a, t b){
	if(a < b) return -1;
	if(a == b) return 0;
	return 1;
}
template <typename it, typename t1>
inline int find(t1 val, it a, int na, bool f_small = 1, bool f_lb = 1){
	int be = 0, en = na - 1;
	if(*a <= *(a + na - 1)){
		if(f_lb == 0) while(be < en){
			int mid = (be + en + 1) / 2;
			if(jud(*(a + mid), val) != 1) be = mid;
			else en = mid - 1;
		}else while(be < en){
			int mid = (be + en) / 2;
			if(jud(*(a + mid), val) != -1) en = mid;
			else be = mid + 1;
		}
		if(f_small && jud(*(a + be), val) == 1) be--;
		if(!f_small && jud(*(a + be), val) == -1) be++;
	} else {
		if(f_lb) while(be < en){
			int mid = (be + en + 1) / 2;
			if(jud(*(a + mid), val) != -1) be = mid;
			else en = mid - 1;
		}else while(be < en){
			int mid = (be + en) / 2;
			if(jud(*(a + mid), val) != 1) en = mid;
			else be = mid + 1;
		}
		if(!f_small && jud(*(a + be), val) == -1) be--;
		if(f_small && jud(*(a + be), val) == 1) be++;
	}
	return be;
}
inline int bitnum(ull nValue){
    nValue = ((0xaaaaaaaaaaaaaaaaull & nValue)>>1) + (0x5555555555555555ull & nValue);
    nValue = ((0xccccccccccccccccull & nValue)>>2) + (0x3333333333333333ull & nValue);
    nValue = ((0xf0f0f0f0f0f0f0f0ull & nValue)>>4) + (0x0f0f0f0f0f0f0f0full & nValue);
    nValue = ((0xff00ff00ff00ff00ull & nValue)>>8) + (0x00ff00ff00ff00ffull & nValue);
    nValue = ((0xffff0000ffff0000ull & nValue)>>16) + (0x0000ffff0000ffffull & nValue);
    nValue = ((0xffffffff00000000ull & nValue)>>32) + (0x00000000ffffffffull & nValue);
	return nValue;
}
long long pow(long long n, long long m, long long mod = 0){
	long long ans = 1;
	long long k = n;
	while(m){
		if(m & 1) {
			ans *= k;
			if(mod) ans %= mod;
		}
		k *= k;
		if(mod) k %= mod;
		m >>= 1;
	}
	return ans;
}

//.........................mi.......feng.......xian.......wai.......jin.......zhi.......challenge...............................................

const int maxn = 250;
const ll mod = 1000000007;
int n, col;
ll have[maxn];
ll dp[5][maxn * 12][maxn * 4], cnt1[maxn * 4][maxn];
ll c[3000][3000];
ll stat1[5][maxn * 4][maxn * 4], radd[5][3][maxn * 4][maxn * 4];

int main(){
//	time_t be = clock();
	ios_base::sync_with_stdio(0);
	for(int i = 0; i < 2500; i++) {
		c[i][0] = 1;
		for(int j = 1; j <= i; j++) {
			c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
			if(c[i][j] > mod) c[i][j] -= mod;
		}
	}

//	freopen("input.txt", "r", stdin);
	scanf("%d%d", &n, &col);
	have[0] = 1;
	for(int i = 1; i <= n; i++) have[i] = have[i - 1] + 3;

	cnt1[0][0] = 1;
	cnt1[1][0] = 1; cnt1[1][1] = 3; cnt1[1][2] = 1;
	for(int i = 2; i <= 4 * n; i++) {
		cnt1[i][0] = 1;
		for(int j = 1; j <= col; j++) {
			cnt1[i][j] += cnt1[i - 1][j];
			cnt1[i][j] += cnt1[i - 1][j - 1] * 3 % mod;
			if(j >= 2) cnt1[i][j] += cnt1[i - 1][j - 2];
			cnt1[i][j] %= mod;
		}
	}

	// most tough part
	for(int i = 0; i < 5; i++) {
		ll all = col - i;
		if(all < 0) break;
		for(int t = 0; t <= n * 12; t++) dp[i][t][0] = c[t][all];
		for(int j = 1; j <= n * 4; j++) for(int t = 0; t <= n * 12 - j * 2; t++) {
			dp[i][t][j] = dp[i][t + 2][j - 1] + dp[i][t + 1][j - 1] - dp[i][t][j - 1];
			if(dp[i][t][j] < 0) dp[i][t][j] += mod;
			while(dp[i][t][j] > mod) dp[i][t][j] -= mod;
		}
	}

	for(int i = -1; i <= n; i++) for(int j = -1; j <= n; j++) for(int k = -1; k <= n; k++){
		int cnt = n * 4; int add = 0;
		if(i != -1) add++;
		if(j != -1) add++;
		if(k != -1) add++;
		int i11 = max(0, i), j11 = max(0, j), k11 = max(0, k);
		cnt -= i11 + j11 + k11;
		pii be = mpr(cnt, n * 4 - (max(i11, j11) + max(k11, j11)) - i11 - k11);
		stat1[add][be.first][be.second]++;
		add++;
		stat1[add][be.first][be.second]++;
		radd[add][0][be.first][be.second]++;
		radd[add][0][be.first - min(i11, k11)][be.second]--;
		radd[add][1][be.first - min(i11, k11)][be.second]++;
		radd[add][1][be.first - max(i11, k11)][be.second - abs(i11 - k11)]--;
		radd[add][2][be.first - max(i11, k11)][be.second - abs(i11 - k11)]++;
		radd[add][2][be.first - n][be.second - abs(i11 - k11) - 2 * (n - max(i11, k11))]--;
	}
	for(int i = 0; i <= 4; i++) for(int k = n * 4; k >= 0; k--) for(int j = n * 4; j >= 0; j--) {
		for(int t = 0; t < 3; t++) {
			radd[i][t][j][k] += radd[i][t][j + 1][k + t], stat1[i][j][k] += radd[i][t][j + 1][k + t];
			if(radd[i][t][j][k] > mod) radd[i][t][j][k] -= mod;
			if(stat1[i][j][k] > mod) stat1[i][j][k] -= mod;
		}
	}
	for(int i = 0; i <= n; i++) for(int j = -1; j <= n; j++) for(int k = -1; k <= n; k++) {
		int cnt = n * 4; ll add = 0;
		if(i != -1) add++;
		if(j != -1) add++;
		if(k != -1) add++;
		int i11 = max(0, i), j11 = max(0, j), k11 = max(0, k);
		cnt -= i11 * 2 + j11 + k11;
		stat1[add][cnt][4 * n - i11 - max(i11, j11) - max(j11, k11) - max(k11, i11)] += 4;
		if(stat1[add][cnt][4 * n - i11 - max(i11, j11) - max(j11, k11) - max(k11, i11)] > mod)
			stat1[add][cnt][4 * n - i11 - max(i11, j11) - max(j11, k11) - max(k11, i11)] -= mod;
	}
	if(col >= 2) for(int i = 0; i <= n; i++) for(int j = 0; j <= n; j++) {
		stat1[2][n * 4 - i * 2 - j * 2][4 * n - i - j - max(i, j) * 2] += 2;
		stat1[2][n * 4 - i * 2 - j * 2][4 * n - i - j - max(i, j) * 2] %= mod;
	}
	ll ans = 0;

	for(int k = n * 4; k >= 0; k--) for(int j = n * 4; j >= 0; j--) for(int t = 0; t < 5; t++) if(stat1[t][k][j] && t <= col){
		ans += dp[t][k * 3 - j * 2][j] * stat1[t][k][j] % mod;
		if(ans > mod) ans -= mod;
/*		for(int i = max(0, col - t - j * 2); i <= col - t; i++){
			if(i > k * 3) break;
			ans += c[k * 3 - j * 2][i] * cnt1[j][col - i - t] % mod * stat1[t][k][j] % mod;
			if(ans > mod) ans -= mod;
		}*/
	}
/*	for(int k = n * 4; k >= 0; k--) for(int j = n * 4; j >= 0; j--) for(int t = 0; t < 5; t++) if(stat1[t][k][j] && t <= col){
		for(int i = max(0, col - t - j * 2); i <= col - t; i++){
			if(i > k * 3) break;
			dp[t + i][j] += c[k * 3 - j * 2][i] * stat1[t][k][j] % mod;
			if(dp[t + i][j] > mod) dp[t + i][j] -= mod;
//			ans += c[k * 3 - j * 2][i] * cnt1[j][col - i - t] % mod * stat1[t][k][j] % mod;
//			if(ans > mod) ans -= mod;
		}
	} */

/*	for(int i = 1; i <= col; i++) {
		int now = i & 1, last = 1 - now;
		for(int j = 0; j < n * 4; j++) for(int t = 0; t < n * 4; t++) {
			if(j == 0) dp[now][j][t] = cnt1[t][i];
			else dp[now][j][t] = dp[now][j - 1][t] + dp[last][j - 1][t];
			if(dp[now][j][t] > mod) dp[now][j][t] -= mod;
			if(i >= col - 4 && stat1[col - i][j][t]) {
				ans += dp[now][j][t] * stat1[col - i][j][t] % mod;
				if(ans > mod) ans -= mod;
			}
		}
	}*/
	for(ll i = 1; i <= col; i++) ans = ans * i % mod;
	cout << ans << endl;
/*	time_t en = clock();
	cout << double ((en - be)) /  CLOCKS_PER_SEC << endl; */

	return 0;
}


/*
 * temp.cpp
 *
 *  Created on: 2012-7-18
 *      Author: BSBandme
 */
//#pragma comment(linker, "/STACK:1024000000,1024000000")
#include <iostream>
#include <fstream>
#include <string.h>
#include <cstdio>
#include <algorithm>
#include <string>
#include <vector>
#include <queue>
#include <cassert>
#include <list>
#include <iomanip>
#include <math.h>
#include <deque>
#include <utility>
#include <map>
#include <set>
#include <bitset>
#include <numeric>
#include <climits>
#include <cctype>
#include <cmath>
#include <cstdlib>
#include <sstream>
#include <time.h>

using namespace std;

#define mpr make_pair
typedef unsigned long long ull;
typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <double, double> pdd;
typedef vector <int> vi;
typedef vector <ll> vll;
typedef vector <double> vd;
typedef vector <string> vs;
typedef map <string, int> mpsi;
typedef map <double, int> mpdi;
typedef map <int, int> mpii;

const double pi = acos(0.0) * 2.0;
const double eps = 1e-12;
const int step[8][2] = {{1, 0}, {-1, 0}, {0, 1}, {0, -1}, {1, 1}, {1, -1}, {-1, 1}, {-1, -1}};

template <class T> inline T abs1(T a) {return a < 0 ? -a : a;}
template <class T> inline T max1(T a, T b, T c = -1234567, T d = -1234567) {
	T ans =  a > b ? a : b;
	if(c != -1234567) ans = max1(ans, c);
	if(d != -1234567) ans = max1(ans, d);
	return ans;
}
template <class T> inline T min1(T a, T b, T c = -1234567, T d = -1234567) {
	T ans = a < b ? a : b;
	if(c != -1234567) ans = min(ans, c);
	if(d != -1234567) ans = min(ans, d);
	return ans;
}
template <class T> inline T gcd1(T a, T b) {
	if(a < b) swap(a, b);
	if(a % b == 0) return b;
	return gcd1(b, a % b);
}
template <class T> inline T lb(T num) {return num & (-num); }
inline int jud(double a, double b){
	if(abs(a) < eps && abs(b) < eps) return 0;
	else if(abs1(a - b) / abs1(a) < eps) return 0;
	if(a < b) return -1;
	return 1;
}
template <typename t>
inline int jud(t a, t b){
	if(a < b) return -1;
	if(a == b) return 0;
	return 1;
}
template <typename it, typename t1>
inline int find(t1 val, it a, int na, bool f_small = 1, bool f_lb = 1){
	int be = 0, en = na - 1;
	if(*a <= *(a + na - 1)){
		if(f_lb == 0) while(be < en){
			int mid = (be + en + 1) / 2;
			if(jud(*(a + mid), val) != 1) be = mid;
			else en = mid - 1;
		}else while(be < en){
			int mid = (be + en) / 2;
			if(jud(*(a + mid), val) != -1) en = mid;
			else be = mid + 1;
		}
		if(f_small && jud(*(a + be), val) == 1) be--;
		if(!f_small && jud(*(a + be), val) == -1) be++;
	} else {
		if(f_lb) while(be < en){
			int mid = (be + en + 1) / 2;
			if(jud(*(a + mid), val) != -1) be = mid;
			else en = mid - 1;
		}else while(be < en){
			int mid = (be + en) / 2;
			if(jud(*(a + mid), val) != 1) en = mid;
			else be = mid + 1;
		}
		if(!f_small && jud(*(a + be), val) == -1) be--;
		if(f_small && jud(*(a + be), val) == 1) be++;
	}
	return be;
}
inline int bitnum(ull nValue){
    nValue = ((0xaaaaaaaaaaaaaaaaull & nValue)>>1) + (0x5555555555555555ull & nValue);
    nValue = ((0xccccccccccccccccull & nValue)>>2) + (0x3333333333333333ull & nValue);
    nValue = ((0xf0f0f0f0f0f0f0f0ull & nValue)>>4) + (0x0f0f0f0f0f0f0f0full & nValue);
    nValue = ((0xff00ff00ff00ff00ull & nValue)>>8) + (0x00ff00ff00ff00ffull & nValue);
    nValue = ((0xffff0000ffff0000ull & nValue)>>16) + (0x0000ffff0000ffffull & nValue);
    nValue = ((0xffffffff00000000ull & nValue)>>32) + (0x00000000ffffffffull & nValue);
	return nValue;
}
long long pow(long long n, long long m, long long mod = 0){
	long long ans = 1;
	long long k = n;
	while(m){
		if(m & 1) {
			ans *= k;
			if(mod) ans %= mod;
		}
		k *= k;
		if(mod) k %= mod;
		m >>= 1;
	}
	return ans;
}

//.........................mi.......feng.......xian.......wai.......jin.......zhi.......challenge...............................................

const int maxn = 250;
const ll mod = 1000000007;
int n, col;
ll have[maxn];
ll dp[5][maxn * 12][maxn * 4];
ll c[3000][3000];
ll stat1[5][maxn * 4][maxn * 4];
int radd[5][3][maxn * 4][maxn * 4];

int main(){
//	time_t be = clock();
	ios_base::sync_with_stdio(0);
	for(int i = 0; i < 2500; i++) {
		c[i][0] = 1;
		for(int j = 1; j <= i; j++) {
			c[i][j] = c[i - 1][j - 1] + c[i - 1][j];
			if(c[i][j] > mod) c[i][j] -= mod;
		}
	}

//	freopen("input.txt", "r", stdin);
	scanf("%d%d", &n, &col);
	have[0] = 1;
	for(int i = 1; i <= n; i++) have[i] = have[i - 1] + 3;

/*	cnt1[0][0] = 1;
	cnt1[1][0] = 1; cnt1[1][1] = 3; cnt1[1][2] = 1;
	for(int i = 2; i <= 4 * n; i++) {
		cnt1[i][0] = 1;
		for(int j = 1; j <= col; j++) {
			cnt1[i][j] += cnt1[i - 1][j];
			cnt1[i][j] += cnt1[i - 1][j - 1] * 3 % mod;
			if(j >= 2) cnt1[i][j] += cnt1[i - 1][j - 2];
			cnt1[i][j] %= mod;
		}
	} */

	// most tough part
	for(int i = 0; i < 5; i++) {
		ll all = col - i;
		if(all < 0) break;
		for(int t = 0; t <= n * 12; t++) dp[i][t][0] = c[t][all];
		for(int j = 1; j <= n * 4; j++) for(int t = 0; t <= n * 12 - j * 2; t++) {
			dp[i][t][j] = dp[i][t + 2][j - 1] + dp[i][t + 1][j - 1] - dp[i][t][j - 1];
			if(dp[i][t][j] < 0) dp[i][t][j] += mod;
			while(dp[i][t][j] > mod) dp[i][t][j] -= mod;
		}
	}

	for(int i = -1; i <= n; i++) for(int j = -1; j <= n; j++) for(int k = -1; k <= n; k++){
		int cnt = n * 4; int add = 0;
		if(i != -1) add++;
		if(j != -1) add++;
		if(k != -1) add++;
		int i11 = max(0, i), j11 = max(0, j), k11 = max(0, k);
		cnt -= i11 + j11 + k11;
		pii be = mpr(cnt, n * 4 - (max(i11, j11) + max(k11, j11)) - i11 - k11);
		stat1[add][be.first][be.second]++;
		add++;
		stat1[add][be.first][be.second]++;
		radd[add][0][be.first][be.second]++;
		radd[add][0][be.first - min(i11, k11)][be.second]--;
		radd[add][1][be.first - min(i11, k11)][be.second]++;
		radd[add][1][be.first - max(i11, k11)][be.second - abs(i11 - k11)]--;
		radd[add][2][be.first - max(i11, k11)][be.second - abs(i11 - k11)]++;
		radd[add][2][be.first - n][be.second - abs(i11 - k11) - 2 * (n - max(i11, k11))]--;
	}
	for(int i = 0; i <= 4; i++) for(int k = n * 4; k >= 0; k--) for(int j = n * 4; j >= 0; j--) {
		for(int t = 0; t < 3; t++) {
			radd[i][t][j][k] += radd[i][t][j + 1][k + t], stat1[i][j][k] += radd[i][t][j + 1][k + t];
			if(radd[i][t][j][k] > mod) radd[i][t][j][k] -= mod;
			if(stat1[i][j][k] > mod) stat1[i][j][k] -= mod;
		}
	}
	for(int i = 0; i <= n; i++) for(int j = -1; j <= n; j++) for(int k = -1; k <= n; k++) {
		int cnt = n * 4; ll add = 0;
		if(i != -1) add++;
		if(j != -1) add++;
		if(k != -1) add++;
		int i11 = max(0, i), j11 = max(0, j), k11 = max(0, k);
		cnt -= i11 * 2 + j11 + k11;
		stat1[add][cnt][4 * n - i11 - max(i11, j11) - max(j11, k11) - max(k11, i11)] += 4;
		if(stat1[add][cnt][4 * n - i11 - max(i11, j11) - max(j11, k11) - max(k11, i11)] > mod)
			stat1[add][cnt][4 * n - i11 - max(i11, j11) - max(j11, k11) - max(k11, i11)] -= mod;
	}
	if(col >= 2) for(int i = 0; i <= n; i++) for(int j = 0; j <= n; j++) {
		stat1[2][n * 4 - i * 2 - j * 2][4 * n - i - j - max(i, j) * 2] += 2;
		stat1[2][n * 4 - i * 2 - j * 2][4 * n - i - j - max(i, j) * 2] %= mod;
	}
	ll ans = 0;

	for(int k = n * 4; k >= 0; k--) for(int j = n * 4; j >= 0; j--) for(int t = 0; t < 5; t++) if(stat1[t][k][j] && t <= col){
		ans += dp[t][k * 3 - j * 2][j] * stat1[t][k][j] % mod;
		if(ans > mod) ans -= mod;
/*		for(int i = max(0, col - t - j * 2); i <= col - t; i++){
			if(i > k * 3) break;
			ans += c[k * 3 - j * 2][i] * cnt1[j][col - i - t] % mod * stat1[t][k][j] % mod;
			if(ans > mod) ans -= mod;
		}*/
	}
/*	for(int k = n * 4; k >= 0; k--) for(int j = n * 4; j >= 0; j--) for(int t = 0; t < 5; t++) if(stat1[t][k][j] && t <= col){
		for(int i = max(0, col - t - j * 2); i <= col - t; i++){
			if(i > k * 3) break;
			dp[t + i][j] += c[k * 3 - j * 2][i] * stat1[t][k][j] % mod;
			if(dp[t + i][j] > mod) dp[t + i][j] -= mod;
//			ans += c[k * 3 - j * 2][i] * cnt1[j][col - i - t] % mod * stat1[t][k][j] % mod;
//			if(ans > mod) ans -= mod;
		}
	} */

/*	for(int i = 1; i <= col; i++) {
		int now = i & 1, last = 1 - now;
		for(int j = 0; j < n * 4; j++) for(int t = 0; t < n * 4; t++) {
			if(j == 0) dp[now][j][t] = cnt1[t][i];
			else dp[now][j][t] = dp[now][j - 1][t] + dp[last][j - 1][t];
			if(dp[now][j][t] > mod) dp[now][j][t] -= mod;
			if(i >= col - 4 && stat1[col - i][j][t]) {
				ans += dp[now][j][t] * stat1[col - i][j][t] % mod;
				if(ans > mod) ans -= mod;
			}
		}
	}*/
	for(ll i = 1; i <= col; i++) ans = ans * i % mod;
	cout << ans << endl;
/*	time_t en = clock();
	cout << double ((en - be)) /  CLOCKS_PER_SEC << endl; */

	return 0;
}


//#define USEPB_DS
#define USETR1
#define CPPELEVEN
#define GPP

/*
 * temp.cpp
 *
 *  Created on: 2012-7-18
 *      Author: BSBandme
 */
//#pragma comment(linker, "/STACK:1024000000,1024000000")

#include <bits/stdc++.h>

using namespace std;

#ifndef CPPELEVEN
#ifdef USETR1
#include <tr1/unordered_map>
#include <tr1/unordered_set>
using namespace tr1;
#endif
#else
#include <unordered_map>
#include <unordered_set>
#endif

#ifdef USEPB_DS
#include <ext/pb_ds/priority_queue.hpp>
#include <ext/pb_ds/assoc_container.hpp>
using namespace __gnu_pbds;
// binomial_heap_tag, rc_binomial_heap_tag, thin_heap_tag, binary_heap_tag
typedef __gnu_pbds::priority_queue<int, greater<int>, pairing_heap_tag> pq_type;
// splay_tree_tag, ov_tree_tag
typedef tree <int, null_type, less <int>, rb_tree_tag, tree_order_statistics_node_update> tree_type;
#endif

#define mpr make_pair
typedef unsigned int ui;
typedef unsigned long long ull;
typedef long long ll;
typedef pair <int, int> pii;
typedef pair <ll, ll> pll;
typedef pair <double, double> pdd;
typedef vector <int> vi;
typedef vector <ll> vll;
typedef vector <double> vd;
typedef vector <string> vs;
typedef map <string, int> mpsi;
typedef map <double, int> mpdi;
typedef map <int, int> mpii;

const double pi = acos(0.0) * 2.0;
const long double eps = 1e-10;
const int step[8][2] = {{-1, 0}, {0, 1}, {1, 0}, {0, -1}, {-1, 1}, {1, 1}, {1, -1}, {-1, -1}};

template <class T> inline T abs1(T a) {return a < 0 ? -a : a;}

#ifndef CPPELEVEN
template <class T> inline T max1(T a, T b) { return b < a ? a : b; }
template <class T> inline T max1(T a, T b, T c) { return max1(max1(a, b), c); }
template <class T> inline T max1(T a, T b, T c, T d) { return max1(max1(a, b, c), d); }
template <class T> inline T max1(T a, T b, T c, T d, T e) { return max1(max1(a, b, c, d), e); }
template <class T> inline T min1(T a, T b) { return a < b ? a : b; }
template <class T> inline T min1(T a, T b, T c) { return min1(min1(a, b), c); }
template <class T> inline T min1(T a, T b, T c, T d) { return min1(min1(a, b, c), d); }
template <class T> inline T min1(T a, T b, T c, T d, T e) { return min1(min1(a, b, c, d), e); }
#else
template <typename t, typename t1>
t min1(t a, t1 b) { return a < b ? a : b; }
template <typename t, typename... arg>
t min1(t a, arg... arr) { return min1(a, min1(arr...)); }
template <typename t, typename t1>
t max1(t a, t1 b) { return a > b ? a : b; }
template <typename t, typename... arg>
t max1(t a, arg... arr) { return max1(a, max1(arr...)); }
#endif

inline int jud(double a, double b){
  if(abs(a) < eps && abs(b) < eps) return 0;
  else if(abs1(a - b) / max(abs1(a), abs1(b)) < eps) return 0;
  if(a < b) return -1;
  return 1;
}
template <typename t> inline int jud(t a, t b){
  if(a < b) return -1;
  if(a == b) return 0;
  return 1;
}

// f_lb == 1代表返回相同的一串的左边界，f_small == 1代表返回如果没有寻找的值返回小的数
template <typename it, typename t1>
inline int find(t1 val, it a, int na, bool f_small = 1, bool f_lb = 1){
  if(na == 0) return 0;
  int be = 0, en = na - 1;
  if(*a <= *(a + na - 1)){
    if(f_lb == 0) while(be < en){
      int mid = (be + en + 1) / 2;
      if(jud(*(a + mid), val) != 1) be = mid;
      else en = mid - 1;
    }else while(be < en){
      int mid = (be + en) / 2;
      if(jud(*(a + mid), val) != -1) en = mid;
      else be = mid + 1;
    }
    if(f_small && jud(*(a + be), val) == 1) be--;
    if(!f_small && jud(*(a + be), val) == -1) be++;
  } else {
    if(f_lb) while(be < en){
      int mid = (be + en + 1) / 2;
      if(jud(*(a + mid), val) != -1) be = mid;
      else en = mid - 1;
    }else while(be < en){
      int mid = (be + en) / 2;
      if(jud(*(a + mid), val) != 1) en = mid;
      else be = mid + 1;
    }
    if(!f_small && jud(*(a + be), val) == -1) be--;
    if(f_small && jud(*(a + be), val) == 1) be++;
  }
  return be;
}

template <class T> inline T lowb(T num) {return num & (-num); }
#ifdef GPP
inline int bitnum(ui nValue) { return __builtin_popcount(nValue); }
inline int bitnum(int nValue) { return __builtin_popcount(nValue); }
inline int bitnum(ull nValue) { return __builtin_popcount(nValue) + __builtin_popcount(nValue >> 32); }
inline int bitnum(ll nValue) { return __builtin_popcount(nValue) + __builtin_popcount(nValue >> 32); }
inline int bitmaxl(ui a) { if(a == 0) return 0; return 32 - __builtin_clz(a); }
inline int bitmaxl(int a) { if(a == 0) return 0; return 32 - __builtin_clz(a); }
inline int bitmaxl(ull a) { int temp = a >> 32; if(temp) return 32 - __builtin_clz(temp) + 32; return bitmaxl(int(a)); }
inline int bitmaxl(ll a) { int temp = a >> 32; if(temp) return 32 - __builtin_clz(temp) + 32; return bitmaxl(int(a)); }
#else
#endif

long long pow(long long n, long long m, long long mod = 0){
  if(m < 0) return 0;
  long long ans = 1;
  long long k = n;
  while(m){
    if(m & 1) {
      ans *= k;
      if(mod) ans %= mod;
    }
    k *= k;
    if(mod) k %= mod;
    m >>= 1;
  }
  return ans;
}

#define  MOD 1000000007
template <class t1, class t2>
inline void add(t1 &a, t2 b, int mod = -1) {
  if(mod == -1) mod = MOD;
  a += b;
  while(a >= mod) a -= mod;
  while(a < 0) a += mod;
}
template <class t>
void output1(t arr) {
  for(int i = 0; i < (int)arr.size(); i++)
    cerr << arr[i] << ' ';
  cerr << endl;
}
template <class t>
void output2(t arr) {
  for(int i = 0; i < (int)arr.size(); i++)
    output1(arr[i]);
}

//....................密..........封..........线..........下..........禁..........止..........hack...............................................

const int maxn = 33;

int ncase;
vector<vi> arr;
char str[30];
int n;
int x, y;

// 0 for whole clock, 1 for whole counter,
// 2 for left clock, 3 for left counter clock
// 4 for right clock, 5 for right counter clock
string rot[10];

void Apply(const string& str);
void Apply(char ch) {
  if (ch == 'u') {
    if (x == 1 && y % n == 0) {
      swap(arr[x][y], arr[x - 1][y]);
      x--;
    } else {
      cerr << "Invalid co " << x << ' ' << y << " for op u" << endl;
      assert(0);
    }
  } else if (ch == 'd') {
    if (x == 0 && y % n == 0) {
      swap(arr[x][y], arr[x + 1][y]);
      x++;
    } else {
      cerr << "Invalid co " << x << ' ' << y << " for op d" << endl;
      assert(0);
    }
  } else if (ch == 'l') {
    if (y > 0) {
      swap(arr[x][y], arr[x][y - 1]);
      y--;
    } else {
      cerr << "Invalid co " << x << ' ' << y << " for op l" << endl;
      assert(0);
    }
  } else if (ch == 'l') {
    if (y > 0) {
      swap(arr[x][y], arr[x][y - 1]);
      y--;
    } else {
      cerr << "Invalid co " << x << ' ' << y << " for op l" << endl;
      assert(0);
    }
  } else if (ch == 'r') {
    if (y < 2 * n) {
      swap(arr[x][y], arr[x][y + 1]);
      y++;
    } else {
      cerr << "Invalid co " << x << ' ' << y << " for op r" << endl;
      assert(0);
    }
  } else Apply(rot[ch - 'A']);
}

void Apply(const string& str) {
  for (auto ch : str) {
    Apply(ch);
  }
}

int main() {
  //............................不要再忘了检查maxn大小了！！！！BSBandme你个SB！！！！........................................
  ios_base::sync_with_stdio(0);
  #ifdef DEBUG //......................................................................................................
  freopen("input.txt", "r", stdin);
  #endif //...........................................................................................................

  scanf("%d", &ncase);
  for (int i1 = 0; i1 < ncase; i1++) {
    scanf("%d", &n);

    // prepare 0
    rot[0] = "";
    for (int i = 0; i < n; i++) {
      rot[0] += "r";
    }
    rot[0] += "u";
    for (int i = 0; i < 2 * n; i++) {
      rot[0] += "l";
    }
    rot[0] += "d";
    for (int i = 0; i < n; i++) {
      rot[0] += "r";
    }

    // prepare 1
    rot[1] = "";
    for (int i = 0; i < n; i++) {
      rot[1] += "l";
    }
    rot[1] += "u";
    for (int i = 0; i < 2 * n; i++) {
      rot[1] += "r";
    }
    rot[1] += "d";
    for (int i = 0; i < n; i++) {
      rot[1] += "l";
    }

    // prepare 2
    rot[2] = "u";
    for (int i = 0; i < n; i++) {
      rot[2] += "l";
    }
    rot[2] += "d";
    for (int i = 0; i < n; i++) {
      rot[2] += "r";
    }

    // prepare 3
    rot[3] = "";
    for (int i = 0; i < n; i++) {
      rot[3] += "l";
    }
    rot[3] += "u";
    for (int i = 0; i < n; i++) {
      rot[3] += "r";
    }
    rot[3] += "d";

    // prepare 5
    rot[5] = "u";
    for (int i = 0; i < n; i++) {
      rot[5] += "r";
    }
    rot[5] += "d";
    for (int i = 0; i < n; i++) {
      rot[5] += "l";
    }

    // prepare 4
    rot[4] = "";
    for (int i = 0; i < n; i++) {
      rot[4] += "r";
    }
    rot[4] += "u";
    for (int i = 0; i < n; i++) {
      rot[4] += "l";
    }
    rot[4] += "d";

    rot[6] = "CFFDAED";

    arr = {{}, {}};
    arr[0].resize(n * 2 + 1);
    arr[1].resize(n * 2 + 1);
    for (int i = 0; i < 2; i++) {
      for (int j = 0; j < 2 * n + 1; j++) {
        scanf("%s", str);
        if (str[0] == 'E') {
          arr[i][j] = -1;
          x = i, y = j;
        } else {
          sscanf(str, "%d", &arr[i][j]);
          if (arr[i][j] > n * 2 + 1) {
            arr[i][j] = n * 2 + 2 + n * 4 + 1 - arr[i][j];
          }
        }
      }
    }

    string ans = "";
    while (y < n) {
      ans += "r";
      Apply('r');
    }
    while (y > n) {
      ans += "l";
      Apply('l');
    }
    if (x == 0) {
      ans += "d";
      Apply('d');
    }

#ifdef DEBUG
    output2(arr);
    cerr << endl;
    for (int i = 0; i < 7; i++) {
      vector<vi> tarr = arr;
      Apply(rot[i]);
      output2(arr);
      cerr << endl;
      arr = tarr;
    }
#endif

    for (int i = 2; i < n * 4; i++) {
      while (true) {
        while (arr[0][n + 1] != i) {
          Apply(rot[1]);
          ans += "B";
        }
        if (arr[0][n] == i - 1) break;
        else {
          if (arr[0][n + 2] > i) {
            Apply(rot[6]);
            ans += 'G';
          } else {
            Apply(rot[0]);
            ans += 'A';
            Apply(rot[6]);
            ans += 'G';
          }
        }
      }
#ifdef DEBUG
      output2(arr);
      cerr << endl;
#endif
    }

    while (arr[0][0] != 1) {
      Apply(rot[1]);
      ans += "B";
    }
    for (int i = 0; i < n; i++) {
      Apply('r');
      ans += "r";
    }
#ifdef DEBUG
    output2(arr);
    cerr << endl;
#endif
    if (arr[1][0] != n * 4 + 1) {
      cout << "SURGERY FAILED" << endl;
    } else {
      cout << "SURGERY COMPLETE" << endl;
      cout << ans << endl;
      for (int i = 0; i < 7; i++) {
        cout << char('A' + i) << ' ' << rot[i] << endl;
      }
      cout << "DONE" << endl;
    }

  }

  return 0;
}


# include <bits/stdc++.h>
//https://codeforces.com/problemset/problem/1280/F
using namespace std;

bool evenPairity(vector<int> p, int k) {
    bool even = true;
    for (auto i = 0u; i < p.size(); i++) {
        for (int j = i - 1; j >= 0; j--) {
            if (p[j] > p[j + 1]) {
                swap(p[j], p[j + 1]);
                // tricky case: We don't actually care about the pairity of permutation
                // with the 'E', just the numbers of the permutation
                if (p[j] != 2 * k + 1 && p[j + 1] != 2 * k + 1) {
                    even = !even;
                }
            }
        }
    }
    return even;
}

void printRotation(int dist) {
    for (int i = 0; i < dist; i++) {
        printf("l");
    }
    printf("u");
    for (int i = 0; i < dist; i++) {
        printf("r");
    }
    printf("d");

}

void simR(vector<int> &a) {
    swap(a[0], a[1]);
    swap(a[1], a[2]);
}

void simB(vector<int> &a, int k) {
    int tmp = a[2 * k + 2];
    for (int i = 2 * k + 2; i != 2 * k; i = (i + 1) % (4 * k + 2)) {
        a[i] = a[(i + 1) % (4 * k + 2)];
    }
    a[2 * k] = tmp;
}

void simD(vector<int> &a, int k) {
    int tmp = a[2 * k];
    for (int i = 2 * k; i != 2 * k + 2; i = (4 * k + 1 + i) % (4 * k + 2)) {
        a[i] = a[(4 * k + 1 + i) % (4 * k + 2)];
    }
    a[2 * k + 2] = tmp;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int cases, k;
    cin >> cases;
    for (int t = 0; t < cases; t++) {
        cin >> k;
        vector<int> perm = vector<int>(4 * k + 2, 0);
        int Eloc = -1;
        for (int i = 0; i < 2; i++) {
            for (int j = 0; j < 2 * k + 1; j++) {
                int ind;
                if (i == 0) {
                    ind = j;
                } else {
                    ind = (4 * k + 1) - j;
                }
                string nxt;
                cin >> nxt;
                if (nxt == "E") {
                    perm[ind] = 2 * k + 1;
                    Eloc = ind;
                } else {
                    perm[ind] = stoi(nxt) - 1;
                    if (perm[ind] >= 2 * k + 1) {
                        perm[ind] = 6 * k + 2 - perm[ind];
                    }
                }
            }
        }
        if (!evenPairity(perm,k)) {
            printf("SURGERY FAILED\n");
            continue;
        }
        printf("SURGERY COMPLETE\n");
        // put E at bottom right
        if (Eloc > 2 * k + 1) {
            while (perm[2 * k + 1] != 2 * k + 1) {
                swap(perm[Eloc], perm[Eloc-1]);
                Eloc--;
                printf("r");
            }
        }else if(Eloc <= 2*k){
            while (perm[2 * k] != 2 * k + 1) {
                swap(perm[Eloc], perm[Eloc+1]);
                Eloc++;
                printf("r");
            }
            swap(perm[2*k+1], perm[2*k]);
            printf("d");
        }
        while (perm[4 * k + 1] != 4 * k + 1) {
            printf("D");
            simD(perm, k);
        }
        for (int i = 4 * k; i >= 2; i--) {
            if (i == perm[i]) {
                continue;
            }
            assert(i + 1 == perm[i + 1]);
            int succLoc = i + 1;
            while (succLoc != 3) {
                if (perm[0] == i) {
                    printf("R");
                    simR(perm);
                }
                printf("B");
                simB(perm, k);
                succLoc = (succLoc + 4*k + 1) % (4 * k + 2);
                if(succLoc==2*k+1){
                    succLoc--;
                }
            }
            while (perm[2] != i) {
                printf("R");
                simR(perm);
            }
            while (perm[4 * k + 1] != 4 * k + 1) {
                printf("D");
                simD(perm, k);
            }
            assert(i == perm[i]);
        }
        printf("\nA ");
        printRotation(k);
        printf("\nB ");
        printRotation(2 * k);
        printf("\nC ");
        for (int i = 0; i < 2 * k; i++) {
            printf("A");
        }
        printf("\nD ");
        for (int i = 0; i < 4 * k; i++) {
            printf("B");
        }
        printf("\nR ");
        for (int i = 0; i < k + 2; i++) {
            printf("B");
        }
        printf("CBCDAA");
        for (int i = 0; i < k + 2; i++) {
            printf("D");
        }
        printf("\nDONE\n");
    }
    return 0;
}


// This problem is not as hard (to me) as some older F problems...
// Another [permutation-puzzle] problem: https://codeforces.com/problemset/problem/1044/E
// Implementation time: 47 minutes...
#ifndef LOCAL
#define NDEBUG
#endif
#include<cassert>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>

int main(){
	std::ios::sync_with_stdio(0);std::cin.tie(0);
	int ntest;std::cin>>ntest;
	while(ntest--){
		std::string out;
		int k;std::cin>>k;
		std::array<std::vector<int>,2> v;

		int emptycol;
		assert((emptycol=-1));

		for(auto& row:v){
			row.resize(k*2+1);
			for(unsigned col=0;col<row.size();++col){
				int& x=row[col];
				if(std::cin>>x){
					/* renumber cells such that the correct arrangement is

+------------------------------------------------------------------------------+
| 3*k+2 3*k+3 3*k+4 ...   4*k   0     1     2     3     ...   k-1   k     k+1  |
|       +--------------------------+      +----------------------------+       |
| 3*k+1 3*k   3*k-1 ...   2*k+3 2*k+2 2*k+1 2*k   2*k-1 ...   k+3   k+2   [E]  |
+------------------------------------------------------------------------------+
					*/
				    if(x<=2*k+1){
					  x=3*k+1+x;
					  if(x>4*k) x-=4*k+1;
				    }else{
					  x=(3*k+1)-(x-(2*k+2));
				    }
				}else{
					std::cin.clear();
					char c;std::cin>>c;
					assert(c=='E');
					x=-1;
					emptycol=col;
				}
			}
		}

		auto& row_contain_empty=v[1][emptycol]<=0 ? v[1] : v[0];
		while((int)emptycol<2*k){
			out+='r';
			std::swap(row_contain_empty[emptycol],row_contain_empty[emptycol+1]);
			++emptycol;
		}

		if(v[0].back()<=0){
			out+='d';
			std::swap(v[0].back(),v[1].back());
		}
		assert(v[1].back()<=0);

		std::vector<int> newp;newp.reserve(4*k+1);
		newp.insert(end(newp),begin(v[0])+k-1,end(v[0]));
		newp.insert(end(newp),++v[1].rbegin(),v[1].rend());
		newp.insert(end(newp),begin(v[0]),begin(v[0])+k-1);
		assert(newp.size()==unsigned(4*k+1));

		v[0].clear(); v[1].clear();

		int start=0;
		// newp[x-start] = new index of block at (home of block with new index x)
		// wraparound

		int i=4*k; // such that block i..4*k are cyclically continuous
		{
			auto posi=int(std::find(begin(newp),end(newp),i)-begin(newp));
			std::rotate(begin(newp),begin(newp)+posi+1,end(newp));
			start=(int)newp.size()-(posi+1);
		}
		assert(newp.back()==i);

		auto const macroA=[&](){
			// macro A: move block at (new) position 0,1,2... to 4*k,0,1,...
			out+='A';
			++start;
			if(start==(int)newp.size()) start=0;
		};

		auto const macroB=[&](){
			// macro B: move block at (new) position 0,1,2 to 1,2,0
			out+='B';
			std::swap(newp[start],newp[(start+1)%newp.size()]);
			std::swap(newp[start],newp[(start+2)%newp.size()]);
		};

		while(i>2){
			assert(newp.back()==(int)newp.size()-1);
			assert(newp[i]==i);

			int const j=i-1;
			auto posj=int(std::find(begin(newp),end(newp),j)-begin(newp));
			if(posj!=j){
				while(start!=std::max(0,posj-1))macroA();
				if(posj==0){ macroB();++posj; }

				while(posj<j){
					assert(start==posj-1);
					macroB();++posj;
					macroA();
				}
			}
			assert(newp[j]==j);
			i=j;
		}

		assert(newp[2]==2);
		if(newp[1]!=1){
			std::cout<<"SURGERY FAILED\n";
			continue;
		}

		assert(newp[0]==0);

		std::cout<<"SURGERY COMPLETE\n"<<out<<'\n';
		{ // print macros
			//std::string LL(k,'l');
			//std::string RR(k,'r');

			std::cout<<"A ";
			for(int z=2*k;z--;) std::cout<<'l';
			std::cout<<'u';
			for(int z=2*k;z--;) std::cout<<'r';
			std::cout<<"d\n";

			std::cout<<"B ";
			for(int z=k;z--;) std::cout<<'l';

			std::cout<<'u';
			for(int z=k;z--;) std::cout<<'l';
			std::cout<<'d';
			for(int z=k;z--;) std::cout<<'r';

			std::cout<<'u';
			for(int z=k;z--;) std::cout<<'r';
			std::cout<<'d';
			for(int z=k;z--;) std::cout<<'l';

			for(int z=k;z--;) std::cout<<'l';
			std::cout<<'u';
			for(int z=k;z--;) std::cout<<'r';
			std::cout<<'d';

			for(int z=k;z--;) std::cout<<'r';
			std::cout<<'u';
			for(int z=k;z--;) std::cout<<'l';
			std::cout<<'d';

			for(int z=k;z--;) std::cout<<'r';
			std::cout<<'\n';
		}
		std::cout<<"DONE\n";
	}
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template < int n, class... T >
typename std::enable_if< (n >= sizeof...(T)) >::type __output_tuple(
    std::ostream &, std::tuple< T... > const &) {}
template < int n, class... T >
typename std::enable_if< (n < sizeof...(T)) >::type __output_tuple(
    std::ostream &os, std::tuple< T... > const &t) {
  os << (n == 0 ? "" : ", ") << std::get< n >(t);
  __output_tuple< n + 1 >(os, t);
}
template < class... T >
std::ostream &operator<<(std::ostream &os, std::tuple< T... > const &t) {
  os << "(";
  __output_tuple< 0 >(os, t);
  os << ")";
  return os;
}
template < class T, class U >
std::ostream &operator<<(std::ostream &os, std::pair< T, U > const &p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
template < class T >
std::ostream &operator<<(std::ostream &os, const std::stack< T > &a) {
  os << "{";
  for(auto tmp = a; tmp.size(); tmp.pop())
    os << (a.size() == tmp.size() ? "" : ", ") << tmp.top();
  os << "}";
  return os;
}
template < class T, class Container, class Compare >
std::ostream &operator<<(std::ostream &os,
    std::priority_queue< T, Container, Compare > a) {
  os << "{ (top) ";
  while(a.size()) os << a.top() << (a.size() == 1 ? "" : ", "), a.pop();
  os << " }";
  return os;
}
template < class T, class Container >
std::ostream &operator<<(std::ostream &os, std::queue< T, Container > a) {
  os << "{ ";
  while(a.size()) os << a.front() << (a.size() == 1 ? "" : ", "), a.pop();
  os << " }";
  return os;
}
#ifdef DEBUG
#if !defined(DEBUG_OUT)
#endif
#define dump(...)                                                                \
  [&]() {                                                                        \
    auto __debug_tap = std::make_tuple(__VA_ARGS__);                             \
    DEBUG_OUT << "[" << __LINE__ << "] " << #__VA_ARGS__ << " = " << __debug_tap \
    << std::endl;                                                      \
  }()
template < class T >
inline void dump2D(T &d, size_t sizey, size_t sizex) {
  for(size_t i = 0; i < sizey; i++) {
    DEBUG_OUT << "\t";
    for(size_t j = 0; j < sizex; j++)
      DEBUG_OUT << d[i][j] << (j + 1 == sizex ? "" : "\t");
    DEBUG_OUT << std::endl;
  }
}
template < class T >
inline void dump1D(T &d, size_t sizey) {
  for(size_t i = 0; i < sizey; i++) {
    DEBUG_OUT << d[i] << (i + 1 == sizey ? "" : " ");
  }
  DEBUG_OUT << std::endl;
}
template <
class T, class = typename std::iterator_traits< decltype(begin(T())) >::value_type,
      class = typename std::enable_if< !std::is_same< T, std::string >::value >::type >
      std::ostream &operator<<(std::ostream &os, const T &a) {
        os << "{";
        for(auto ite = begin(a); ite != end(a); ++ite)
          os << (ite == begin(a) ? "" : ", ") << *ite;
        os << "}";
        return os;
      }
#else
#define dump(...) (42)
#define dump2D(...) (42)
#define dump1D(...) (42)
template <
class T, class = typename std::iterator_traits< decltype(begin(T())) >::value_type,
      class = typename std::enable_if< !std::is_same< T, std::string >::value >::type >
      std::ostream &operator<<(std::ostream &os, const T &a) {
        for(auto ite = begin(a); ite != end(a); ++ite)
          os << (ite == begin(a) ? "" : " ") << *ite;
        return os;
      }
#endif
inline void hash_combine2(std::size_t& seed, size_t a)
{
  seed ^= a + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

inline size_t comball(initializer_list<size_t> l)
{
  size_t seed = 0;
  for(auto e : l) {
    hash_combine2(seed, e);
  }
  return seed;
}

template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
  std::hash<T> hasher;
  seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

using uint = unsigned;

using HASH = tuple<size_t, size_t, size_t>;

enum TYEPS { INPUT, REFERENCE, OP };
struct Data {
  int type = INPUT;
  string name = "";
  HASH hsh;
  char op = '-';

  Data *refer = 0, *l = 0, *r = 0;

  bool operator==(const Data &b) const {
    return hsh == b.hsh;
  }
};

set<string> ava;
vector<string> avas;

Data* makeInput(string name) {
  Data *d = new Data;
  d->type = INPUT;
  d->name = name;
  ava.erase(name);
  d->hsh = HASH(hash<string>{}(name), hash<string>{}(name + name), hash<char>{}(name[0]));
  return d;
}
Data* makeOp(Data * l, Data * r, char op) {
  Data *d = new Data;
  d->type = OP;
  d->l = l;
  d->r = r;
  d->op = op;

  size_t a, b, c;
  size_t x, y, z;
  tie(a, b, c) = l->hsh;
  tie(x, y, z) = r->hsh;
  size_t seed0 = comball({a, z, hash<string>{}(string(3, op)), y, c});
  size_t seed1 = comball({x, hash<string>{}(string(1, op)), b, c});
  size_t seed2 = comball({a, y, c, hash<char>{}(op), x});

  d->hsh = HASH(seed0, seed1, seed2);
  return d;
}

int n;

int OPN = 4;
char ops[] = {'$', '^', '#', '&'};

map<string, Data*> data;

void reset(string name) {
  if(!data.count(name)) data[name] = makeInput(name);
}

map<tuple<int, string, HASH>, Data*> uni;
int k = 0;
stringstream ans;
set<Data*> used;

void dfs(Data*& p, bool root = 0) {
  if(!p) return;
  auto hs = make_tuple(p->type, p->name + p->op, p->hsh);
  if(uni.count(hs)) {
    p = uni[hs];
    return;
  }
  uni[hs] = p;
  if(used.count(p)) return;
  used.insert(p);
  switch(p->type) {
    case INPUT:
      if(root && p->name != "res") {
        k++;
        ans << "res=" << p->name << "\n";
      }
      break;
    case OP:
      dfs(p->l);
      dfs(p->r);

      string name = "res";
      if(!root) {
        name = avas.back();
        avas.pop_back();
      }
      k++;
      ans << name << "=" << p->l->name << p->op << p->r->name << "\n";
      assert(p->l->name.size());
      assert(p->r->name.size());
      p->name = name;
      break;
  }
}

int main() {
  std::ios::sync_with_stdio(false), std::cin.tie(0);
  for(int i = 0; i < 1000; i++) {
    ava.insert("a" + to_string(i));
    ava.insert("b" + to_string(i));
    ava.insert("c" + to_string(i));
  }
  cin >> n;
  for(int i = 0; i < n; i++) {
    string s;
    cin >> s;
    int uku = s.find('=');
    assert(uku != -1);
    string LHS = s.substr(0, uku);
    string RHS = s.substr(uku + 1, int(s.size()) - uku - 1);
    int op = -1;
    string a1, a2;
    for(int o = 0; o < OPN; o++) {
      int id = RHS.find(ops[o]);
      if(id >= 0) {
        op = o;
        a1 = RHS.substr(0, id);
        a2 = RHS.substr(id + 1, int(RHS.size()) - id - 1);
      }
    }
    if(op >= 0) {
      reset(a1);
      reset(a2);
      assert(a1.size());
      assert(a2.size());
      data[LHS] = makeOp(data[a1], data[a2], ops[op]);
    } else {
      reset(RHS);
      data[LHS] = data[RHS];
    }
  }
  reset("res");
  assert(ava.size() >= 1000);
  avas = vector<string>(ava.begin(), ava.end());
  dfs(data["res"], 1);
  dump("done");
  ans << flush;
  cout << k << "\n";
  cout << ans.str()
  return 0;
}


// https://codeforces.com/contest/1156/submission/53644962 (Dukkha)
#include <iostream>
#include <string>
#include <unordered_map>
#include <unordered_set>
#include <vector>

using namespace std;

unordered_set<string> ss;

struct V {
	string s;
	char op;
	V *u, *v;
	int d;
	V(string &s) {
		this->s = s;
		op = 0;
		ss.insert(s);
		d = 0;
	}
	V(char op, V *u, V *v) {
		s = "";
		this->op = op; this->u = u; this->v = v;
		d = max(u->d, v->d) + 1;
	}
};

struct X {
	size_t operator() (V *w) const {
		return w->op ^ (size_t) w->u ^ (size_t) w->v;
	}
};

struct Y {
	bool operator() (V *w1, V *w2) const {
		return w1->op == w2->op && w1->u == w2->u && w1->v == w2->v;
	}
};

vector<V *> list;

static string getX() {
	string s = "xxxx";
	do {
		s[0] = (char) ('a' + rand() % 26);
		s[1] = (char) ('a' + rand() % 26);
		s[2] = (char) ('a' + rand() % 26);
		s[3] = (char) ('a' + rand() % 26);
	} while (ss.find(s) != ss.end());
	return s;
}

void dfs(V *w, string s) {
	if (w->s == "") {
		w->s = s;
		ss.insert(w->s);
		list.push_back(w);
		dfs(w->u, getX());
		dfs(w->v, getX());
	}
}

int main() {
	srand(time(NULL));
	int n;
	cin >> n;
	unordered_map<string, V *> sv;
	unordered_set<V *, X, Y> vv;
	while (n--) {
		string s;
		cin >> s;
		int m = s.length();
		int p = -1, q = -1;
		for (int j = 0; j < m; j++)
			if (s[j] == '=')
				p = j;
			else if (s[j] == '$' || s[j] == '^' || s[j] == '#' || s[j] == '&')
				q = j;
		string lvalue = s.substr(0, p);
		if (q == -1) {
			string rvalue = s.substr(p + 1, m - p - 1);
			V *v = sv[rvalue];
			if (v == NULL)
				sv[rvalue] = v = new V(rvalue);
			sv[lvalue] = v;
		} else {
			string arg1 = s.substr(p + 1, q - p - 1);
			string arg2 = s.substr(q + 1, m - q - 1);
			char op = s[q];
			V *u = sv[arg1];
			if (u == NULL)
				sv[arg1] = u = new V(arg1);
			V *v = sv[arg2];
			if (v == NULL)
				sv[arg2] = v = new V(arg2);
			V *w = new V(op, u, v);
			auto it = vv.find(w);
			if (it == vv.end())
				vv.insert(w);
			else
				w = *it;
			sv[lvalue] = w;
		}
	}
	V *w = sv["res"];
	if (w == NULL) {
		cout << 0 << '\n';
		return 0;
	}
	if (w->op == 0) {
		if (w->s == "res")
			cout << 0 << '\n';
		else {
			cout << 1 << '\n';
			cout << "res=" << w->s << '\n';
		}
		return 0;
	}
	dfs(w, "res");
	cout << list.size() << '\n';
	sort(list.begin(), list.end(), [] (V *u, V *v) { return u->d < v->d; });
	for (V *w : list)
		cout << w->s << '=' << w->u->s << w->op << w->v->s << '\n';
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
using ll = long long;
template < int n, class... T >
typename std::enable_if< (n >= sizeof...(T)) >::type __output_tuple(
    std::ostream &, std::tuple< T... > const &) {}
template < int n, class... T >
typename std::enable_if< (n < sizeof...(T)) >::type __output_tuple(
    std::ostream &os, std::tuple< T... > const &t) {
  os << (n == 0 ? "" : ", ") << std::get< n >(t);
  __output_tuple< n + 1 >(os, t);
}
template < class... T >
std::ostream &operator<<(std::ostream &os, std::tuple< T... > const &t) {
  os << "(";
  __output_tuple< 0 >(os, t);
  os << ")";
  return os;
}
template < class T, class U >
std::ostream &operator<<(std::ostream &os, std::pair< T, U > const &p) {
  os << "(" << p.first << ", " << p.second << ")";
  return os;
}
template < class T >
std::ostream &operator<<(std::ostream &os, const std::stack< T > &a) {
  os << "{";
  for(auto tmp = a; tmp.size(); tmp.pop())
    os << (a.size() == tmp.size() ? "" : ", ") << tmp.top();
  os << "}";
  return os;
}
template < class T, class Container, class Compare >
std::ostream &operator<<(std::ostream &os,
    std::priority_queue< T, Container, Compare > a) {
  os << "{ (top) ";
  while(a.size()) os << a.top() << (a.size() == 1 ? "" : ", "), a.pop();
  os << " }";
  return os;
}
template < class T, class Container >
std::ostream &operator<<(std::ostream &os, std::queue< T, Container > a) {
  os << "{ ";
  while(a.size()) os << a.front() << (a.size() == 1 ? "" : ", "), a.pop();
  os << " }";
  return os;
}
#ifdef DEBUG
#if !defined(DEBUG_OUT)
#endif
#define dump(...)                                                                \
  [&]() {                                                                        \
    auto __debug_tap = std::make_tuple(__VA_ARGS__);                             \
    DEBUG_OUT << "[" << __LINE__ << "] " << #__VA_ARGS__ << " = " << __debug_tap \
    << std::endl;                                                      \
  }()
template < class T >
inline void dump2D(T &d, size_t sizey, size_t sizex) {
  for(size_t i = 0; i < sizey; i++) {
    DEBUG_OUT << "\t";
    for(size_t j = 0; j < sizex; j++)
      DEBUG_OUT << d[i][j] << (j + 1 == sizex ? "" : "\t");
    DEBUG_OUT << std::endl;
  }
}
template < class T >
inline void dump1D(T &d, size_t sizey) {
  for(size_t i = 0; i < sizey; i++) {
    DEBUG_OUT << d[i] << (i + 1 == sizey ? "" : " ");
  }
  DEBUG_OUT << std::endl;
}
template <
class T, class = typename std::iterator_traits< decltype(begin(T())) >::value_type,
      class = typename std::enable_if< !std::is_same< T, std::string >::value >::type >
      std::ostream &operator<<(std::ostream &os, const T &a) {
        os << "{";
        for(auto ite = begin(a); ite != end(a); ++ite)
          os << (ite == begin(a) ? "" : ", ") << *ite;
        os << "}";
        return os;
      }
#else
#define dump(...) (42)
#define dump2D(...) (42)
#define dump1D(...) (42)
template <
class T, class = typename std::iterator_traits< decltype(begin(T())) >::value_type,
      class = typename std::enable_if< !std::is_same< T, std::string >::value >::type >
      std::ostream &operator<<(std::ostream &os, const T &a) {
        for(auto ite = begin(a); ite != end(a); ++ite)
          os << (ite == begin(a) ? "" : " ") << *ite;
        return os;
      }
#endif
inline void hash_combine2(std::size_t& seed, size_t a)
{
  seed ^= a + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

inline size_t comball(initializer_list<size_t> l)
{
  size_t seed = 0;
  for(auto e : l) {
    hash_combine2(seed, e);
  }
  return seed;
}

template <class T>
inline void hash_combine(std::size_t& seed, const T& v)
{
  std::hash<T> hasher;
  seed ^= hasher(v) + 0x9e3779b9 + (seed<<6) + (seed>>2);
}

using uint = unsigned;

using HASH = tuple<size_t, size_t, size_t>;

enum TYEPS { INPUT, REFERENCE, OP };
struct Data {
  int type = INPUT;
  string name = "";
  HASH hsh;
  char op = '-';

  Data *refer = 0, *l = 0, *r = 0;

  bool operator==(const Data &b) const {
    return hsh == b.hsh;
  }
};

set<string> ava;
vector<string> avas;

Data* makeInput(string name) {
  Data *d = new Data;
  d->type = INPUT;
  d->name = name;
  ava.erase(name);
  d->hsh = HASH(hash<string>{}(name), hash<string>{}(name + name), hash<char>{}(name[0]));
  return d;
}
Data* makeOp(Data * l, Data * r, char op) {
  Data *d = new Data;
  d->type = OP;
  d->l = l;
  d->r = r;
  d->op = op;

  size_t a, b, c;
  size_t x, y, z;
  tie(a, b, c) = l->hsh;
  tie(x, y, z) = r->hsh;
  size_t seed0 = comball({a, z, hash<string>{}(string(3, op)), y, c});
  size_t seed1 = comball({x, hash<string>{}(string(1, op)), b, c});
  size_t seed2 = comball({a, y, c, hash<char>{}(op), x});

  d->hsh = HASH(seed0, seed1, seed2);
  return d;
}

int n;

int OPN = 4;
char ops[] = {'$', '^', '#', '&'};

map<string, Data*> data;

void reset(string name) {
  if(!data.count(name)) data[name] = makeInput(name);
}

map<tuple<int, string, HASH>, Data*> uni;
int k = 0;
stringstream ans;
set<Data*> used;

void dfs(Data*& p, bool root = 0) {
  if(!p) return;
  auto hs = make_tuple(p->type, p->name + p->op, p->hsh);
  if(uni.count(hs)) {
    p = uni[hs];
    return;
  }
  uni[hs] = p;
  if(used.count(p)) return;
  used.insert(p);
  switch(p->type) {
    case INPUT:
      if(root && p->name != "res") {
        k++;
        ans << "res=" << p->name << "\n";
      }
      break;
    case OP:
      dfs(p->l);
      dfs(p->r);

      string name = "res";
      if(!root) {
        name = avas.back();
        avas.pop_back();
      }
      k++;
      ans << name << "=" << p->l->name << p->op << p->r->name << "\n";
      assert(p->l->name.size());
      assert(p->r->name.size());
      p->name = name;
      break;
  }
}

int main() {
  std::ios::sync_with_stdio(false), std::cin.tie(0);
  for(int i = 0; i < 1000; i++) {
    ava.insert("a" + to_string(i));
    ava.insert("b" + to_string(i));
    ava.insert("c" + to_string(i));
  }
  cin >> n;
  for(int i = 0; i < n; i++) {
    string s;
    cin >> s;
    int uku = s.find('=');
    assert(uku != -1);
    string LHS = s.substr(0, uku);
    string RHS = s.substr(uku + 1, int(s.size()) - uku - 1);
    int op = -1;
    string a1, a2;
    for(int o = 0; o < OPN; o++) {
      int id = RHS.find(ops[o]);
      if(id >= 0) {
        op = o;
        a1 = RHS.substr(0, id);
        a2 = RHS.substr(id + 1, int(RHS.size()) - id - 1);
      }
    }
    if(op >= 0) {
      reset(a1);
      reset(a2);
      assert(a1.size());
      assert(a2.size());
      data[LHS] = makeOp(data[a1], data[a2], ops[op]);
    } else {
      reset(RHS);
      data[LHS] = data[RHS];
    }
  }
  reset("res");
  assert(ava.size() >= 1000);
  avas = vector<string>(ava.begin(), ava.end());
  dfs(data["res"], 1);
  dump("done");
  ans << flush;//
  cout << k << "\n";
  cout << ans.str()
  return 0;
}


#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef pair<ll,ll> pll;
typedef vector<bool> vb;
const ll oo = 0x3f3f3f3f3f3f3f3f;
const double eps = 1e-9;
#define sz(c) ll((c).size())
#define all(c) begin(c), end(c)
#define FOR(i,a,b) for (ll i = (a); i < (b); i++)
#define FORD(i,a,b) for (ll i = (b)-1; i >= (a); i--)
#define mp make_pair
#define pb push_back
#define eb emplace_back
#define xx first
#define yy second
#define TR(X) ({ if(1) cerr << "TR: " << (#X) << " = " << (X) << endl; })

bool is_op(char c) {
	for (char d: "$^#&") if (c == d) return true;
	return false;
}

int main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL);

	map<string,ll> var2node;
	ll m = 0;
	vector<tuple<char,ll,ll>> nodes;
	vector<string> original_var;
	map<tuple<char,ll,ll>,ll> operations;

	auto add_node = [&](string a) {
		original_var.pb(a);
		nodes.eb('=',-1,m);
		var2node[a] = m++;
	};

	ll n; cin >> n;
	while (n--) {
		string asn; cin >> asn;
		ll ii = 0;
		while (asn[ii] != '=') ii++;

		string a = asn.substr(0,ii);
		asn = asn.substr(ii+1), ii = 0;
		while (ii < sz(asn) && !is_op(asn[ii])) ii++;

		if (ii == sz(asn)) {
			string b = asn;
			if (!var2node.count(b)) {
				add_node(b);
			}
			var2node[a] = var2node[b];
		} else {
			string b = asn.substr(0,ii), c = asn.substr(ii+1);
			char op = asn[ii];
			if (!var2node.count(b)) {
				add_node(b);
			}
			if (!var2node.count(c)) {
				add_node(c);
			}
			tuple<char,ll,ll> tpl = make_tuple(op,var2node[b],var2node[c]);
			if (!operations.count(tpl)) {
				nodes.pb(tpl);
				operations[tpl] = m++;
			}
			var2node[a] = operations[tpl];
		}
	}

	if (!var2node.count("res")) {
		cout << 0 << endl;
		return 0;
	}

	auto fresh = [&]() {
		string s = "aaaa";
		while (var2node.count(s)) {
			FOR(i,0,4) s[i] = 'a' + rand() % 26;
		}
		var2node[s] = -1;
		return s;
	};

	vector<string> res;
	map<ll,string> new_var;

	function<string(ll)> rec = [&](ll cur) {
		if (new_var.count(cur)) return new_var[cur];

		char op;
		ll a, b;
		tie(op,a,b) = nodes[cur];
		if (op == '=') return original_var[cur];

		string stra = rec(a), strb = rec(b);

		string str = (cur == var2node["res"]) ? "res" : fresh();
		res.pb(str + "=" + stra + op + strb);
		return new_var[cur] = str;
	};

	string lst = rec(var2node["res"]);
	if (lst != "res") res.pb("res=" + lst);
	cout << sz(res) << endl;
	for (string str: res) cout << str << endl;

}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;

#define MOD ll(1e9 + 7)
#define MAXN 200010
#define LG 33
#define inf (ll)1e18

template<typename T> inline T smin(T &a, const T &b) { return a > b ? a = b : a; }
template<typename T> inline T smax(T &a, const T &b) { return a < b ? a = b : a; }
inline void add(ll &l, const ll &r) { l = (l + r) % MOD; }
ll gcd(ll v, ll u) { return u ? gcd(u, v % u) : v; }
ll po(ll v, ll u) { return u ? (po(v * v % MOD, u >> 1) * (u & 1 ? v : 1) % MOD) : 1; }

ll n, m, a[MAXN], b[MAXN], answer;

int main() {
	ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);
	cin >> n >> m;
	for (int i = 1; i <= n; i++)
		cin >> a[i];
	for (ll p = 1; (n * p) <= m; p++) {
		b[n] = min(a[n], p * m - n * ((p * (p - 1) / 2)));
		for (int i = n - 1; i; i--)
			b[i] = min(a[i], b[i + 1] - p);
		if (b[1] < (p + n * ((p * (p - 1) / 2))))
			continue;
		ll r = m - n * p, v = b[1], res = b[1];
		for (int i = 2; i <= n; i++) {
			ll can = min(b[i] - (v += p), r);
			v += can; r -= can; res += v;
		}
		smax(answer, res);
	}
	cout << answer << endl;
	system("pause");
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

const int N = 1e5 + 7;

ll c[N], p[N];

int main()
{
	ios::sync_with_stdio(false), cin.tie(0);

	ll n, m;
	cin >> n >> m;

	for (int i=0; i<n; i++)
		cin >> c[i];

	ll ans = 0;
	for (ll k=1; k * n <= m; k++)
	{
		p[n-1] = m * k - (k - 1) * k / 2 * n;
		p[n-1] = min(p[n-1], c[n-1]);

		for (int i=n-2; i>=0; i--)
			p[i] = min(p[i+1] - k, c[i]);

		if (p[0] < k * (k+1) / 2LL)
			break;

		ll space = m - n * k;

		ll out = p[0];
		ll prev = p[0];

		for (int i=1; i<n; i++)
		{
			prev = prev + k;
			int shift_size = min(space, p[i] - prev);
			space -= shift_size;
			prev += shift_size;
			out += prev;
		}

		ans = max(ans, out);
	}

	cout << ans << "\n";

	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cassert>
#define SIZE 200005

using namespace std;
typedef long long int ll;
typedef pair <ll,int> P;

ll A[SIZE];
ll zan[SIZE];
P st[SIZE];

int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=0;i<n;i++) scanf("%lld",&A[i]);
	ll ret=0;
	int AAA=0;
	for(int k=1;k*n<=m;k++)
	{
		ll sum=0;
		bool up=true;
		for(int i=0;i<n;i++)
		{
			zan[i]=A[i];
			zan[i]-=(ll) (i+1)*(ll) k+(ll) n*(ll) k*(ll) (k-1)/2LL;
			if(zan[i]<0)
			{
				up=false;
				break;
			}
			sum+=A[i]-zan[i];
		}
		if(!up) break;
		AAA++;
		int sz=0;
		for(int i=n-1;i>=0;i--)
		{
			if(sz>0&&st[sz-1].first<=zan[i]) continue;
			st[sz++]=P(zan[i],i);
		}
		//printf("%lld\n",sum);
		//for(int i=0;i<sz;i++) printf("[%lld %d] ",st[i].first,st[i].second);puts("");
		int nm=st[sz-1].first;
		int all=m-k*n;
		if(nm/k>=all) sum+=(ll) min(nm/k,all)*(ll) n*(ll) k;
		else
		{
			sum+=(ll) nm*(ll) n;
			ll cn=(ll) all*(ll) k-nm;cn=min(cn,(ll) all);
			for(int i=sz-2;i>=0;i--)
			{
				ll cnt=st[i].first-st[i+1].first;
				int gt=n-st[i+1].second-1;
				//gt+(k-1)コ を一回やると、nm-=(k-1),all--
				//kコ を一回やると、nm-=k,all--
				//nm<all*k の間は前者をやってよい <=> cn 回までできる
				ll g=min(cn,cnt);
				sum+=(ll) gt*(ll) g;
				cn-=g;
			}
		}
		ret=max(ret,sum);
	}
	if(ret==0) assert(AAA==0);
	printf("%I64d\n",ret);
	return 0;
}


#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <cstring>
#include <cassert>
#define SIZE 200005

using namespace std;
typedef long long int ll;
typedef pair <ll,int> P;

ll A[SIZE];
ll zan[SIZE];
P st[SIZE];

int main()
{
	int n,m;
	scanf("%d %d",&n,&m);
	for(int i=0;i<n;i++) scanf("%lld",&A[i]);
	ll ret=0;
	int AAA=0;
	for(int k=1;k*n<=m;k++)
	{
		ll sum=0;
		bool up=true;
		for(int i=0;i<n;i++)
		{
			zan[i]=A[i];
			zan[i]-=(ll) (i+1)*(ll) k+(ll) n*(ll) k*(ll) (k-1)/2LL;
			if(zan[i]<0)
			{
				up=false;
				break;
			}
			sum+=A[i]-zan[i];
		}
		if(!up) break;
		AAA++;
		ll bef=sum;
		int sz=0;
		for(int i=n-1;i>=0;i--)
		{
			if(sz>0&&st[sz-1].first<=zan[i]) continue;
			st[sz++]=P(zan[i],i);
		}
		//printf("%lld\n",sum);
		//for(int i=0;i<sz;i++) printf("[%lld %d] ",st[i].first,st[i].second);puts("");
		ll nm=st[sz-1].first;
		int all=m-k*n;
		if(nm/k>=all) sum+=(ll) min(nm/k,all)*(ll) n*(ll) k;
		else
		{
			sum+=(ll) nm*(ll) n;
			ll cn=(ll) all*(ll) k-nm;cn=min(cn,(ll) all);
			for(int i=sz-2;i>=0;i--)
			{
				ll cnt=st[i].first-st[i+1].first;
				int gt=n-st[i+1].second-1;
				//gt+(k-1)�R �������ƁAnm-=(k-1),all--
				//k�R �������ƁAnm-=k,all--
				//nm<all*k �̊Ԃ͑O�҂�����Ă悢 <=> cn ��܂łł���
				ll g=min(cn,cnt);
				sum+=(ll) gt*(ll) g;
				cn-=g;
			}
		}
		assert(sum>=bef);
		ret=max(ret,sum);
	}
	//if(ret==0) assert(AAA==0);
	printf("%lld\n",ret);
	return 0;
}


//                       <................. be name khoda ....................>
//                        Balance                  treeeee
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
const int N = 301;
int n, v, e;
long long sum = 0;
int a[ N + 1 ], fa[ N + 1 ], b[ N + 1 ];
vector<int> nei[ N + 1 ];
int getFather( int i){
	if( fa[ i ] == -1 )
		return i;
	return fa[ i ] = getFather( fa[ i ] );
}
bool vis[ N + 1 ];
vector<int> ve;
void dfs(int cur, int p ){
	sum += 1ll * (a[ cur ] - b[ cur ]);
	vis[ cur ] = true;
	ve.push_back( cur );
	for(int ne : nei[ cur ] )
		if( ne != p ) dfs( ne, cur );
}
bool mark[ N + 1 ];
vector<pair<int,pair<int,int> > > curans;
int currentVo, last;
vector<pair<int,int> > curv;
vector<pair<int,pair<int,int> > > ans;
void check( int cur){
	if( currentVo < 0ll ){
		last = -currentVo;
		currentVo = min( 0ll, currentVo + a[ cur ] );
	}
	if( currentVo > 0ll){
		int x = v - a[ cur ];
		last = currentVo;
		currentVo = max( currentVo - x, 0ll );
	}
	return;
}
void dfs2( int cur, int p ){
	if( !currentVo ) return;
	if( cur != p ) curv.push_back( mp(cur,p) );
	if( cur != p ) check( cur );
	for(int ne : nei[ cur ] ){
		if( ne != p && !mark[ ne ]) dfs2( ne, cur );
	}
	return;
}
main(){
	ios::sync_with_stdio(false);
	cin.tie( 0 );
	cin >> n >> v >> e;
	fill( fa, fa + N + 1, -1);
	for(int i = 0;i < n; i++) cin >> a[ i ];
	for(int j = 0;j < n; j++) cin >> b[ j ];
	for(int i = 0;i < e; i++){
		int u, v;
		cin >> u >> v;
		u--,v--;
		int f = getFather( u );
		int ff = getFather( v );
		if( ff != f ){
		    fa[ v ] = f;
			nei[ v ].push_back( u );
			nei[ u ].push_back( v );
		}
	}
	for(int i = 0; i < n; i++){
		if( vis[ i ] ) continue;
		sum = 0ll;
		ve.resize( 0 );
		dfs( i, i );
		if( sum != 0 ) return cout << "NO",0;
		for(int j = (int)ve.size() - 1; j > -1; j--){
			int J = ve[ j ];
			mark[ ve[ j ] ] = true;
			currentVo = a[ J ] - b[ J ];
			curv.resize( 0 );
			last = 0;
			if( !currentVo ) continue;
		//	cout << J+1 <<endl;
			dfs2( ve[ j ], ve[ j ] );
			if(a[ J ] - b[ J ] > 0 ){
				a[ curv.back().first ] = a[ curv.back().first ] + last;
				a[ curv.back().second ] = a[ curv.back().second ] - last;
				ans.push_back( mp( last, mp( curv.back().second, curv.back().first ) ) );
		//		cout << last <<' ' << curv.back().second + 1 << curv.back().first + 1 <<endl;
			}
			else{
				a[ curv.back().first ] = a[ curv.back().first ] - last;
				a[ curv.back().second ] = a[ curv.back().second ] + last;
				ans.push_back( mp( last, curv.back()  ) );
		//		cout << last <<' ' << curv.back().first + 1 << curv.back().second + 1 <<endl;
			}
			for(int k = (int)curv.size()-2; k > -1; k--){
				int x = 0;
			       	if( a[ J ] - b[ J ] > 0 ){
					x = min( a[ curv[ k ].second ], v - a[ curv[ k ].first ] );
					a[ curv[ k ].first ] += x;
					a[ curv[ k ].second ] -= x;
					ans.push_back( mp( x, mp(curv[ k ].second, curv[ k ].first ) ) );
		//			cout << last <<' ' << curv[ k ].second + 1 << curv[ k ].first + 1 <<endl;
				}
				else{
					x = min( a[ curv[ k ].first ], v - a[ curv[ k ].second ] );
					a[ curv[ k ].first ] -= x;
					a[ curv[ k ].second ] += x;
					ans.push_back( mp( x, mp(curv[ k ].first, curv[ k ].second ) ) );
		//			cout << last <<' ' << curv[k].first + 1 << curv[k].second + 1 <<endl;
				}
			}
		}
	}
	cout << (int)ans.size() <<endl;
	for(int i = 0;i < ans.size(); i++)
		cout << ans[i].second.first + 1<<' ' << ans[i].second.second + 1<<' ' << ans[i].first << endl;

}


//                       <................. be name khoda ....................>
//                        Balance                  treeeee
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define int long long
const int N = 301;
int n, v, e;
long long sum = 0;
int a[ N + 1 ], s[ N + 1 ], fa[ N + 1 ], b[ N + 1 ];
vector<int> nei[ N + 1 ];
int getFather( int i){
	if( fa[ i ] == -1 )
		return i;
	return fa[ i ] = getFather( fa[ i ] );
}
int setFather( int i, int f ){
	int gi = -1;
	while( fa[ i ] != -1 ){
		if( gi != f && gi!=-1) fa[ gi ] = f;
		i = fa[ i ];
		gi = i;
	}
	if( i != f ) fa[ i ] = f;
	return i;
}
bool vis[ N + 1 ];
vector<int> ve;
void dfs(int cur, int p ){
	sum += 1ll * (a[ cur ] - b[ cur ]);
	vis[ cur ] = true;
	ve.push_back( cur );
	for(int ne : nei[ cur ] )
		if( ne != p ) dfs( ne, cur );
}
bool mark[ N + 1 ];
vector<pair<int,pair<int,int> > > curans;
int currentVo, last;
vector<pair<int,int> > curv;
vector<pair<int,pair<int,int> > > ans;
void check( int cur){
	if( currentVo < 0 ){
		last = -currentVo;
		currentVo = min( 0, currentVo + a[ cur ] );
	}
	if( currentVo > 0){
		int x = v - a[ cur ];
		last = currentVo;
		currentVo = max( currentVo - x, 0 );
	}
	return;
}
void dfs2( int cur, int p ){
	if( !currentVo ) return;
	if( cur != p ) curv.push_back( mp(cur,p) );
	if( cur != p ) check( cur );
	for(int ne : nei[ cur ] ){
		if( ne != p && !mark[ ne ]) dfs2( ne, cur );
	}
	return;
}
main(){
	ios::sync_with_stdio(false);
	cin.tie( 0 );
	cin >> n >> v >> e;
	fill( fa, fa + N + 1, -1);
	for(int i = 0;i < n; i++) cin >> a[ i ];
	for(int j = 0;j < n; j++) cin >> b[ j ];
	for(int i = 0;i < e; i++){
		int u, v;
		cin >> u >> v;
		u--,v--;
		int f = getFather( u );
		if( setFather( v , f) != f ){
			nei[ v ].push_back( u );
			nei[ u ].push_back( v );
		}
	}
	for(int i = 0; i < n; i++){
		if( vis[ i ] ) continue;
		sum = 0ll;
		ve.resize( 0 );
		dfs( i, i );
		if( sum != 0 ) return cout << "NO",0;
		for(int j = (int)ve.size() - 1; j > -1; j--){
			int J = ve[ j ];
			mark[ ve[ j ] ] = true;
			currentVo = a[ J ] - b[ J ];
			curv.resize( 0 );
			last = 0;
			if( !currentVo ) continue;
		//	cout << J+1 <<endl;
			dfs2( ve[ j ], ve[ j ] );
			if(a[ J ] - b[ J ] > 0 ){
				a[ curv.back().first ] = a[ curv.back().first ] + last;
				a[ curv.back().second ] = a[ curv.back().second ] - last;
				ans.push_back( mp( last, mp( curv.back().second, curv.back().first ) ) );
		//		cout << last <<' ' << curv.back().second + 1 << curv.back().first + 1 <<endl;
			}
			else{
				a[ curv.back().first ] = a[ curv.back().first ] - last;
				a[ curv.back().second ] = a[ curv.back().second ] + last;
				ans.push_back( mp( last, curv.back()  ) );
		//		cout << last <<' ' << curv.back().first + 1 << curv.back().second + 1 <<endl;
			}
			for(int k = (int)curv.size()-2; k > -1; k--){
				int x = 0;
			       	if( a[ J ] - b[ J ] > 0 ){
					x = min( a[ curv[ k ].second ], v - a[ curv[ k ].first ] );
					a[ curv[ k ].first ] += x;
					a[ curv[ k ].second ] -= x;
					ans.push_back( mp( x, mp(curv[ k ].second, curv[ k ].first ) ) );
		//			cout << last <<' ' << curv[ k ].second + 1 << curv[ k ].first + 1 <<endl;
				}
				else{
					x = min( a[ curv[ k ].first ], v - a[ curv[ k ].second ] );
					a[ curv[ k ].first ] -= x;
					a[ curv[ k ].second ] += x;
					ans.push_back( mp( x, mp(curv[ k ].first, curv[ k ].second ) ) );
		//			cout << last <<' ' << curv[k].first + 1 << curv[k].second + 1 <<endl;
				}
			}
		}
	}
	cout << (int)ans.size() <<endl;
	for(int i = 0;i < ans.size(); i++)
		cout << ans[i].second.first + 1<<' ' << ans[i].second.second + 1<<' ' << ans[i].first << endl;

}


// ConsoleApplication1.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <iostream>
#include <string>
#include <algorithm>
#include <cmath>
#include <iomanip>
#include <map>
#include <queue>
#include<set>
#include<stack>
#include<cstdio>
#include <unordered_map>
#include <functional>
#define PI 3.14159265

using namespace std;

vector<int> node[301];
int b[301];
int c[301];
int parent[301];
stack<int> mo;
stack<int> le;
vector<pair<pair<int, int>,int>> ans;

bool dfs(int now, int s, int t)
{
    for (int i = 0; i < node[now].size(); i++)
    {
        int next = node[now][i];
        if (parent[next] != -1) continue;
        parent[next] = now;
        if (next == t)
        {
            return true;
        }
        if (dfs(next, s, t)) return true;
    }
    return false;
}

void write(int s, int t,int d,int v)
{
    if (parent[t] == s)
    {
        ans.push_back(make_pair(make_pair(s, t), d));
        c[s] -= d;
        c[t] += d;
        return;
    }
    else if (c[parent[t]] >= d)
    {
        c[t] += d;
        c[parent[t]] -= d;
        ans.push_back(make_pair(make_pair(s, parent[t]), d));
    }
    else
    {
        ans.push_back(make_pair(make_pair(parent[t],t), c[parent[t]]));
        int temp = c[parent[t]];
        c[parent[t]] = 0;
        write(s, parent[t], d ,v);
        ans.push_back(make_pair(make_pair(parent[t], t), d - temp));
        c[t] += d;
        c[parent[t]] = temp;

    }

}

int main() {

    std::ios_base::sync_with_stdio(false);

    int n, v, e;
    cin >> n >> v >> e;
    int sum = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> c[i];
        sum += c[i];
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> b[i];
        sum -= b[i];
        if (c[i] < b[i])
        {
            le.push(i);
        }
        else if (c[i]>b[i])
        {
            mo.push(i);
        }
    }
    if (sum != 0)
    {
        cout << "NO" << endl;
        return 0;
    }
    for (int i = 0; i < e; i++)
    {
        int u, v;
        cin >> u >> v;
        node[u].push_back(v);
        node[v].push_back(u);
    }

    while (mo.size() > 0)
    {
        int s = mo.top();
        int t = le.top();
        memset(parent, -1, sizeof(parent));
        parent[s] = 0;
        dfs(s, s, t);
        int d = min(c[s] - b[s], b[t] - c[t]);
        write(s, t, d, v);
        if (c[s] == b[s]) mo.pop();
        if (c[t] == b[t]) le.pop();
    }
    cout << ans.size() << endl;
    for (int i = 0; i < ans.size(); i++)
    {
        cout << ans[i].first.first << " " << ans[i].first.second << " " << ans[i].second << endl;
    }
   // system("PAUSE");
    return 0;
}


//                       <................. be name khoda ....................>
//                        Balance                  treeeee
#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
const int N = 301;
int n, v, e;
long long sum = 0;
int a[ N + 1 ], fa[ N + 1 ], b[ N + 1 ];
vector<int> nei[ N + 1 ];
int getFather( int i){
	if( fa[ i ] == -1 )
		return i;
	return fa[ i ] = getFather( fa[ i ] );
}
bool vis[ N + 1 ];
bool mark[ N + 1 ];
int currentVo;
vector<pair<int,pair<int,int> > > ans;
void check( int cur,int p, int &x){
    x = abs( currentVo );
	if( currentVo < 0 )
		currentVo = min( 0, currentVo + a[ cur ] );
	if( currentVo > 0)
		currentVo = max( currentVo - (v - a[ cur ]), 0 );
	if( currentVo ) x = -1;
	return;
}
bool isg=false;
void dfs2( int cur, int p ){
    int x = 0;
	if( !currentVo ) return;
	if( cur != p ) check( cur,p, x );
	for(int ne : nei[ cur ] )
	    if( ne != p && !mark[ ne ]) dfs2( ne, cur );
    if( cur == p ) return;
	if( isg ){
	    if( x == -1 )
		    x = min(v - a[ cur ], a[ p ]);
		a[ cur ] += x;
		a[ p ] -= x;
        ans.push_back( mp(x,mp(p,cur)));
	}
	else{
	    if( x == -1)
		    x = min( v-a[ p ], a[ cur ]);
		a[ cur ] -= x;
		a[ p ] += x;
		ans.push_back( mp(x,mp(cur,p)));
	}
}
void dfs(int cur, int p ){
	sum += 1ll * (a[ cur ] - b[ cur ]);
	vis[ cur ] = true;
	ve.push_back( cur );
	for(int ne : nei[ cur ] )
		if( ne != p ) dfs( ne, cur );
	mark[ cur ] = true;
	currentVo = a[ cur ] - b[ cur ];
	isg = (currentVo > 0);
	if( currentVo )
	    dfs2( cur, cur );
}
main(){
	ios::sync_with_stdio(false);
	cin.tie( 0 );
	cin >> n >> v >> e;
	fill( fa, fa + N + 1, -1);
	for(int i = 0;i < n; i++) cin >> a[ i ];
	for(int j = 0;j < n; j++) cin >> b[ j ];
	for(int i = 0;i < e; i++){
		int u, v;
		cin >> u >> v;
		u--,v--;
		int f = getFather( u );
		int ff = getFather( v );
		if( ff != f ){
		    fa[ v ] = f;
			nei[ v ].push_back( u );
			nei[ u ].push_back( v );
		}
	}
	for(int i = 0; i < n; i++){
		if( vis[ i ] ) continue;
		sum = 0ll;
		dfs( i, i );
		if( sum != 0 ) return cout << "NO",0;
	}
	cout << (int)ans.size() <<endl;
	for(int i = 0;i < ans.size(); i++)
		cout << ans[i].second.first + 1<<' ' << ans[i].second.second + 1<<' ' << ans[i].first << endl;

}


#include <bits/stdc++.h>
using namespace std;

#define ms(s, n) memset(s, n, sizeof(s))
#define FOR(i, a, b) for(int i = (a); i < (b); i++)
#define FORd(i, a, b) for(int i = (a) - 1; i >= (b); i--)
#define sz(a) int((a).size())
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
typedef pair<int, int> pi;
typedef vector<int> vi;
typedef vector<pi> vii;
ll gcd(ll a, ll b) {ll r; while (b != 0) {r = a % b; a = b; b = r;} return a;}
ll lcm(ll a, ll b) {return a / gcd(a, b) * b;}

struct recommendation {
	int l, r;
	int max;
	ld pro;
};

bool compare(recommendation a, recommendation b) {
	if (a.l == b.l) return a.r >= b.r;
	return a.l < b.l;
}

const int maxn = 100010;
const int maxq = 5010;
int n, q;
int a[maxn];
int amax;
recommendation re[maxq];
vi nex[maxq];
vi head;
ld pro[maxq];
map<pi, ld> mp;

ld cal(int cur, int k, int val) {
	if (mp.count(make_pair(cur, k))) return mp[make_pair(cur, k)];
	if (re[cur].max + k > val) return 0.0;
	if (!sz(nex[cur])) {
		if (re[cur].max + k == val) return 1.0 - re[cur].pro;
		else return 1.0;
	}
	ld res = 1;
	FOR(i, 0, sz(nex[cur])) {
		ld tmp = 0;
		tmp += (1.0 - re[cur].pro) * cal(nex[cur][i], k, val);
		if (re[cur].max + k < val) tmp += re[cur].pro * cal(nex[cur][i], k + 1, val);
		res *= tmp;
	}
	return mp[make_pair(cur, k)] = res;
}

void cal(int val) {
	pro[val] = 1;
	FOR(i, 0, sz(head)) {
		mp.clear();
		int cur = head[i];
		pro[val] *= cal(cur, 0, val + amax);
	}
}

int go(int cur, int r) {
	int i;
	for (i = cur + 1; i < q && re[i].r <= r; i++) {
		if (cur != -1) nex[cur].push_back(i);
		else head.push_back(i);
		i = go(i, re[i].r);
	}
	return i - 1;
}

void solve() {
	scanf("%d%d", &n, &q);
	amax = 0;
	FOR(i, 0, n) {
		scanf("%d", a + i);
		amax = max(amax, a[i]);
	}
	FOR(i, 0, q) {
		cin>>re[i].l>>re[i].r>>re[i].pro; re[i].l--; re[i].r--;
		re[i].max = 0;
		FOR(j, re[i].l, re[i].r + 1) re[i].max = max(re[i].max, a[j]);
	}
	sort(re, re + q, compare);
	go(-1, INT_MAX);
	FOR(i, 0, q + 1) cal(i);
	ld ans = 0;
	FOR(i, 0, q + 1) {
		if (!i) ans += 1.0 * (amax + i) * pro[i];
		else ans += 1.0 * (amax + i) * (pro[i] - pro[i - 1]);
	}
	cout<<fixed<<setprecision(9)<<ans;
}

int main() {
#ifdef _LOCAL_
	freopen("in.txt", "r", stdin); freopen("out.txt", "w", stdout);
#endif
	solve();
#ifdef _LOCAL_
	printf("\nTime elapsed: %dms", 1000 * clock() / CLOCKS_PER_SEC);
#endif
	return 0;
}


#include <cstring>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <memory.h>
#include <cassert>
#include <unistd.h>
using namespace std;

typedef long long LL;
typedef unsigned long long ULL;
// typedef unsigned long long ulong;
typedef unsigned int uint;
typedef unsigned short ushort;
typedef unsigned char uchar;

#define MAX_INT 0x7fffffff
#define MIN_INT 0x80000000
#define MAX_UINT 0xffffffff

template<class T> inline T SQR(T x) { return x * x; }
template<class T> inline string TOSTR(const T & x) { stringstream ss; ss << x; return ss.str(); }
template<class T> void UPDATE_MIN(T &x,T y){ if(y < x) { x = y;} }
template<class T> void UPDATE_MAX(T &x,T y){ if(x < y) { x = y;} }

#define FORN(i,n) for(int (i)=0;(i)<(int)(n);(i)++)
#define FOR(i,s,n) for(int (i)=s;(i)<(int)(n);(i)++)
#define ITER(c,itr) for(__typeof((c).begin()) itr=(c).begin();itr!=(c).end();itr++)
#define SWAP(a, b, tmp) {__typeof(a) tmp = a; a = b; b = tmp;}
#ifndef ONLINE_JUDGE
    #define EPR(args...) fprintf (stderr, args)
#else
    #define EPR(args...) 1
#endif
#if 1 // disable print
    #undef EPR
    #define EPR(args...) 1
#endif

#define SZ(x) ((int)(x).size())
#define FORV(i,v) FORN(i,SZ(v))
#define MAX(a,b) ((a > b) ? a : b)
#define MIN(a,b) ((a < b) ? a : b)

#define PR(x) cout << (x) << endl
#define PRF(x) cout << setprecision(10) << x << endl
#define POW2(x) (1ll<<(x))

int gcd(int a, int b){return a?gcd(b%a,a):b;}
LL gcd(LL a, LL b){return a?gcd(b%a,a):b;}
LL powmod(LL a, LL p, LL m){LL r=1;while(p){if(p&1)r=r*a%m;p>>=1;a=a*a%m;}return r;}

const int MOD = 1000 * 1000 * 1000 + 7;
const double PI = 3.1415926535897932384626433832795l;

#define MAXN 100000
#define MAXQ 5099
int N, Q;
int A[MAXN + 100];
int M[MAXN + 100][14];

void RMQ_prepair() {
    int i, j;
    //initialize M for the intervals with length 1
    for (i = 0; i < N; i++)
        M[i][0] = i;
    //compute values from smaller to bigger intervals
    for (j = 1; 1 << j <= N; j++) {
        for (i = 0; i + (1 << j) - 1 < N; i++) {
            int x = M[i][j - 1];
            int y = M[i + (1 << (j - 1))][j - 1];
            if (A[x] > A[y])
                M[i][j] = x;
            else
                M[i][j] = y;
        }
    }
}

int RMQ(int i, int j) {
    if (i == j)
        return i;
    int k = (int)log2(j - i);
    int x = M[i][k];
    int y = M[j - (1 << k) + 1][k];
    if (A[x] > A[y])
        return x;
    else
        return y;
}

typedef struct {
    int l;
    int r;
    double p;
    int max_up;
    double a[MAXQ];
    double prod_p[MAXQ];
    double prod_q[MAXQ];
} Seg;

typedef struct {
    int l;
    int r;
    double p;
} Miniseg;

Miniseg minisegs[MAXQ];
Seg segs[MAXQ];
int seg_i = 0;

int compare(Miniseg a, Miniseg b) {
    if (a.l < b.l) return 1;
    if (a.l > b.l) return 0;

    if (a.r > b.r) return 1;
    if (a.r < b.r) return 0;
    return 0;
}

int calc(int curseg_i) {
    Seg &seg = segs[curseg_i];
    // printf("%d %d: %d\n", seg.l, seg.r, RMQ(seg.l, seg.r));
    int mx = A[RMQ(seg.l, seg.r)];
    // int mx = 0;
    // printf("MX %d %d = %d\n", seg.l, seg.r, mx);

    FORN(i, Q + 1) seg.prod_p[i] = 1.0;
    FORN(i, Q + 1) seg.prod_q[i] = 1.0;
    seg.prod_p[0] = 0.0;

    while (1) {
        int next_seg_i = seg_i;
        if (next_seg_i >= Q)
            break;
        Seg &next_seg = segs[next_seg_i];
        if (!(seg.l <= next_seg.l && next_seg.r <= seg.r))
            break;

        seg_i++;
        // printf("Proc %d: %d\n", curseg_i, seg_i - 1);
        int ch_mx = calc(next_seg_i);

        int diff = mx - ch_mx;
        // printf("adding %d -> %d (diff %d - %d = %d)\n", next_seg_i, curseg_i, mx, ch_mx, diff);
        FOR(i, diff + 1, Q + 1) {
            // printf("  prod_p: %f[%d] * %f[%d] = ", seg.prod_p[i - diff], i - diff, next_seg.a[i - 1], i - 1);
            seg.prod_p[i - diff] *= next_seg.a[i - 1];
            // printf("%f\n", seg.prod_p[i - diff]);
        }
        FOR(i, diff, Q + 1) {
            // printf("  prod_q: %f[%d] * %f[%d] = ", seg.prod_q[i - diff], i - diff, next_seg.a[i], i);
            seg.prod_q[i - diff] *= next_seg.a[i];
            // printf("%f\n", seg.prod_q[i - diff]);
        }
    }
    double q = 1 - seg.p;
    FORN(i, Q + 2) {
        seg.a[i] = seg.prod_p[i] * seg.p + seg.prod_q[i] * q;
        // if (i == 0) {
        // printf("at %d (seg %d): %f * %f + %f * %f = %f\n", i, curseg_i, seg.prod_p[i], seg.p, seg.prod_q[i], q, seg.a[i]);
        // }
    }
    return mx;
}

int main() {
    cin >> N >> Q;
    FORN(i, N) cin >> A[i];
    RMQ_prepair();
    FORN(i, Q) {
        int l, r;
        double p;
        cin >> l >> r >> p;
        l--;
        r--;
        minisegs[i] = {l, r, p};
    }
    // cout << "Sorting" << endl;
    sort(minisegs, minisegs + Q, compare);
    // cout << "Copying" << endl;
    // FORN(i, Q) {
        // cout << minisegs[i].l << " " << minisegs[i].r << " " << minisegs[i].p << endl;
    // }
    FORN(i, Q) {
        segs[i] = {minisegs[i].l, minisegs[i].r, minisegs[i].p};
    }
    segs[Q] = {0, N, 0.0};
    // cout << "Start calc" << endl;
    int mx = calc(Q);
    // int mx = 1;

    Seg &seg = segs[Q];
    double res = seg.a[0] * mx;
    // printf("%d: %f\n", mx, seg.a[0]);
    FOR(j, 1, Q + 1) {
        // printf("%d: %f\n", mx + j, seg.a[j]);
        res += (mx + j) * (seg.a[j] - seg.a[j - 1]);
    }
    printf("%.10f\n", res);
    return 0;
}