Zeyad wants to commit n crimes in Egypt and not be punished at the end. There are several types of crimes. For example, bribery is a crime but is not considered such when repeated twice. Therefore, bribery is not considered a crime when repeated an even number of times. Speeding is a crime, but is not considered such when repeated a number of times which is a multiple of five.More specifically, c conditions on crime repetitions are known. Each condition describes the crime type ti and its multiplicity mi. If the number of times Zeyad committed the crime ti is a multiple of mi, Zeyad will not be punished for crime ti. Some crimes may be listed more than once. In this case fulfilling at least one condition for this crime is enough to not be punished for it. Of course, if for certain crime the number of times Zeyad committed it is zero, he is innocent with respect to this crime.Now Zeyad is interested in a number of ways he can commit exactly n crimes without any punishment.The order of commiting the crimes matters. More formally, two ways, sequences w1 and w2, of committing n crimes are equal if w1i = w2i, for all 1 ≤ i ≤ n.

The first line contains two integers n and c (0 ≤ n ≤ 1018, 0 ≤ c ≤ 1000) — the number of crimes Zeyad would like to commit and the number of conditions he is aware of. Then the definitions for c conditions follow. There are 26 types of crimes. Each crime definition consists of crime type — a capital Latin letter — and its multiplicity.  The multiplicity of each crime is a positive integer number and the product of all multiplicities does not exceed 123. Some conditions may be repeated in the input more than once. Crime of multiplicity 1 is not yielding any punishment regardless of the number of times it was committed. The strictness of the law is compensated by the fact that it's non-mandatory. Obviously, if some crime is not listed in the set of conditions, then Zeyad will not consider it, as committing it would unavoidably lead to the punishment. Please, do not use the %lld specificator to read or write 64-bit integers in С++. It is preferred to use the cin stream (you may also use the %I64d specificator).

Output the number of different ways Zeyad can commit exactly n crimes with no punishment modulo 12345.

NoteIn the first test case, the 16 ways are: AAAAA, AAABB, AABAB, AABBA, ABAAB, ABABA, ABBAA, BAAAB, BAABA, BABAA, BBAAA, ABBBB, BABBB, BBABB, BBBAB, BBBBA.

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

class Matrix{
public:
    static const int MOD = 12345;
    typedef long long LL;
    int n,m;
    int value[128][128];
    Matrix():n(),m(){}
    Matrix(int c):n(c),m(c){
        memset(value,0,sizeof(value));
        while(c--) value[c][c]=1;
    }
    Matrix(int n, int m):n(n),m(m){
        memset(value,0,sizeof(value));
    }
    int* operator [](int r){return value[r];}
    const int* operator [](int r) const{return value[r];}
    struct SizeMismatch{};
    Matrix& operator *=(const Matrix& c){return *this=*this*c;}
    Matrix operator ~() const{
        Matrix ret(m,n);
        for(int i=0;i<m;i++) for(int j=0;j<n;j++) ret[i][j]=value[j][i];
        return ret;
    }
    Matrix operator *(const Matrix& c) const{
        if(m!=c.n) throw SizeMismatch();
        Matrix ret(n,c.m);
        for(int k=0;k<m;k++) for(int i=0;i<n;i++) for(int j=0;j<c.m;j++)
            ret[i][j]=(ret[i][j]+LL(value[i][k])*c[k][j])%MOD;
        return ret;
    }
    Matrix pow(long long e) const{
        if(n!=m) throw SizeMismatch();
        Matrix ret=n,c=*this;
        for(;e;e>>=1,c*=c) if(e&1) ret*=c;
        return ret;
    }
};

int encode(const vector<int>& u, const vector<int>& o){
    int ret=0;
    for(size_t i=o.size()-1;~i;i--){
        ret*=o[i];
        ret+=u[i]%o[i];
    }
    return ret;
}

vector<int> decode(int x, const vector<int>& o){
    vector<int> u;
    for(size_t i=0;i<o.size();i++){
        u.push_back(x%o[i]);
        x/=o[i];
    }
    return u;
}

bool check(const vector<int>& u, const vector<int> w[]){
    for(size_t i=0,j;i<u.size();i++){
        for(j=0;j<w[i].size();j++) if(u[i]%w[i][j]==0) break;
        if(j==w[i].size()) return false;
    }
    return true;
}

int main(){
    long long n;
    int c,ans=0,sz=1;
    scanf("%I64d%d",&n,&c);
    vector<int> w[26],o;
    for(int i=0;i<c;i++){
        char str[5];
        int now;
        scanf("%s%d",str,&now);
        w[*str-'A'].push_back(now);
    }
    for(int i=0;i<26;i++) if(w[i].size()){
        sort(w[i].begin(),w[i].end());
        w[i].erase(unique(w[i].begin(),w[i].end()),w[i].end());
        o.push_back(1);
        for(size_t j=0;j<w[i].size();j++)
            o.back()*=w[i][j]/__gcd(o.back(),w[i][j]);
        sz*=o.back();
        w[o.size()-1]=w[i];
    }
    Matrix a(sz,sz);
    for(int i=0;i<sz;i++){
        vector<int> u=decode(i,o);
        for(auto& x:u){
            x++;
            a[i][encode(u,o)]++;
            x--;
        }
    }
    a=a.pow(n);
    for(int i=0;i<sz;i++) if(check(decode(i,o),w)) ans+=a[0][i];
    printf("%d\n",ans%a.MOD);
}

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<map>
#include<cmath>
#include<vector>
#include<string>
using namespace std;
const int N=200;
const int mod=12345;
typedef __int64 LL;
#define pb push_back

int n;

void mul(int aa[N][N],int bb[N][N]){
    int cc[N][N];
    memset(cc,0,sizeof(cc));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<n;k++){
                cc[i][j]+=aa[i][k]*bb[k][j]%mod;cc[i][j]%=mod;
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            aa[i][j]=cc[i][j];
        }
    }
}

void _powm(int aa[N][N],LL b){
    int cc[N][N];
    memset(cc,0,sizeof(cc));
    for(int i=0;i<n;i++)cc[i][i]=1;
    while(b){
        if(b&1){
            mul(cc,aa);
        }
        mul(aa,aa);b/=2;
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            aa[i][j]=cc[i][j];
        }
    }
}

int sta[30],top;
int tt[N][N],aa[N][N],bb[N][N];
vector<int> vv[30];
vector<int> ww[30];
int fun(int sta2,int xx){
    //printf("fun\n");
    int sta1=0;
    //printf("%d %d\n",top,ww[0].size());
    for(int i=0;i<top;i++){
        for(int j=0;j<ww[i].size()-1;j++){
            //printf("%dvv\n",vv[i][j]);
            int x=sta2%ww[i][j+1]/ww[i][j];
            //printf("%dx\n",x);
            if(i!=xx){
                sta1+=x*ww[i][j];
            }
            else {
                x++;x%=vv[sta[i]][j];
                sta1+=x*ww[i][j];
            }
        }
    }
    //printf("%dfun\n",sta1);
    return sta1;
}
int check(int sta){
    int cnt=0;
    for(int i=0;i<top;i++){
        for(int j=0;j<ww[i].size()-1;j++){
            int x=sta%ww[i][j+1]/ww[i][j];
            if(x==0){
                cnt++;break;
            }
        }
    }
    return cnt==top;
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi
    LL a,b;
    while(scanf("%I64d%I64d",&a,&b)!=EOF){
        for(int i=0;i<26;i++)vv[i].clear();
        for(int i=0;i<b;i++){
            char ss[2];int v;scanf("%s%d",ss,&v);
            vv[ss[0]-'A'].pb(v);
        }
        for(int i=0;i<26;i++){
            sort(vv[i].begin(),vv[i].end());
        }

        top=0;
        int cnt=0;
        for(int i=0;i<26;i++){
            if(vv[i].size()){
                if(vv[i][0]>1)sta[top++]=i;
                else if(vv[i][0]==1){
                    cnt++;
                }
            }
        }

        int sz=1;
        for(int i=0;i<top;i++){
            ww[i].clear();
            for(int j=0;j<vv[sta[i]].size();j++){
                ww[i].pb(sz);
                sz*=vv[sta[i]][j];
            }
            ww[i].pb(sz);
        }
        //for(int i=0;i<top;i++)printf("%d %d\n",sta[i],ww[i].size());
        //printf("%dsz %dtop %dcb\n",sz,top,cnt);
//        for(int i=0;i<3;i++){
//            printf("%dsz\n",vv[i].size());
//        }
        n=sz;
        memset(tt,0,sizeof(tt));
        for(int i=0;i<sz;i++){
            tt[i][i]=cnt;
            for(int j=0;j<top;j++){
                int x=fun(i,j);
                //printf("%d %dj %dx\n",i,j,x);
                tt[i][x]++;
            }
        }
//        for(int i=0;i<sz;i++){
//            for(int j=0;j<sz;j++){
//                printf("%d ",tt[i][j]);
//            }printf("\n");
//        }
        _powm(tt,a);
//        for(int i=0;i<sz;i++){
//            for(int j=0;j<sz;j++){
//                printf("%d ",tt[i][j]);
//            }printf("\n");
//        }
        int ans=0;
        for(int i=0;i<sz;i++){
            if(check(i)){
                ans+=tt[0][i];ans%=mod;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

#include <iostream>
#include <cstdio>
#include <vector>
#include <string>
#include "memory.h"

using namespace std;

const int MOD = 12345;
vector<int> a;
vector<vector<int> > p;

int mul;

struct Matr
{
	vector<vector<int> > a;
	Matr()
	{
		a.assign(mul, vector<int> (mul, 0));
	}
};
Matr operator *(Matr &a, Matr &b)
{
	Matr ans;
	for (int i = 0; i < mul; i++)
		for (int j = 0; j < mul; j++)
			for (int k = 0; k < mul; k++)
				ans.a[i][j] = (ans.a[i][j] + a.a[i][k]*b.a[k][j])%MOD;
	return ans;
}
int getNumber(vector<int> &b)
{
	int ans = 0;
	for (int i = 25; i >= 0; i--)
		if (a[i] != 0)
			ans = ans*a[i] + b[i];
	return ans;
}
void getVector(int num, vector<int> &b)
{
	for (int i = 0; i < 26; i++)
		if (a[i] == 0)
			b[i] = 0;
		else
		{
			b[i] = num % a[i];
			num /= a[i];
		}
}
int main()
{
	a.assign(26, 0);
	p.assign(26, vector<int> (0) );
	long long n;
	int kol;
	cin >> n >> kol;
	mul = 1;
	for (int i = 0; i < kol; i++)
	{
		char ch;
		cin >> ch;
		int x;
		cin >> x;
		mul *= x;
		int num = ch - 'A';
		if (a[num] == 0)
			a[num]++;
		a[num] *= x;
		p[num].push_back(x);
	}
	/*for (int i=  0; i < 26; i++)
		cout << a[i] << " ";
	cout << endl;
	cout << endl;
	*/
	for (int i = 0; i < mul; i++)
	{
		vector<int> b(26, 0);
		getVector(i, b);
		/*for (int i=  0; i < 26; i++)
			cout << b[i] << " ";
		cout << endl;*/
	}

	Matr matr;
	vector<int> b(26, 0);
	for (int i = 0; i < mul; i++)
	{
		getVector(i, b);
		for (int j = 0; j < 26; j++)
			if (a[j] != 0)
			{
				b[j] = (b[j]+1)%a[j];
				int num = getNumber(b);
				matr.a[i][num]++;
				if (matr.a[i][num] >= MOD)
					matr.a[i][num] -= MOD;
				b[j] = (b[j]+a[j]-1)%a[j];
			}
	}
	/*for (int i = 0; i < 2; i++)
	{
		for (int j = 0; j < 2; j++)
			cout << matr.a[i][j] << " ";
		cout << endl;
	}*/
	Matr e;
	for (int i = 0; i < mul; i++)
		e.a[i][i] = 1;
	while (n > 0)
	{
		if (n&1)
			e = e*matr;
		matr = matr*matr;
		n >>= 1;
		/*for (int i = 0; i < 2; i++)
		{
			for (int j = 0; j < 2; j++)
				cout << matr.a[i][j] << " ";
			cout << endl;
		}*/
	}
	int ans = 0;
	for (int i = 0; i < mul; i++)
	{
		bool flag = true;
		vector<int> b(26, 0);
		getVector(i, b);
		for (int j = 0; j < 26; j++)
			if (a[j] > 0)
			{
				int ind = 1;
				for (int k = 0; k < p[j].size(); k++)
				{
					if (b[j]%p[j][k] == 0)
						ind = 0;
				}
				if (ind == 1)
					flag = false;
			}
		if (flag)
			ans = (ans+e.a[0][i])%MOD;
	}
	cout  << ans << endl;
	return 0;
}

/*
ID: hamed_51
PROG: ?
LANG: C++
*/

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <queue>
#include <stack>
#include <list>
#include <deque>
#include <assert.h>
#include <ctime>
#include <bitset>
#include <numeric>
#include <complex>
using namespace std;

#if (_win32 || __win32__)
#define lld "%i64d"
#else
#define lld "%lld"
#endif

#define FOREACH(i, c) for(__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define FOR(i, a, n) for (register int i = (a); i < (int)(n); ++i)
#define Size(n) ((int)(n).size())
#define all(n) (n).begin(), (n).end()
#define ll long long
#define pb push_back
#define error(x) cerr << #x << " = " << x << endl;
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define point complex<double>
#define X real()
#define Y imag()
#define EPS 1e-8

struct mat {
	int w[123];
};

int bel[10], val[10], sz, lim;
int table[123][123];
const int MOD = 12345;
mat unit, c;

void mul(mat &a, mat b) {
	FOR(i, 0, lim) c.w[i] = 0;
	FOR(i, 0, lim) FOR(j, 0, lim) {
		c.w[table[i][j]] += a.w[i]*b.w[j];
		c.w[table[i][j]] %= MOD;
	}
	a = c;
}

mat power(ll y) {
	if (y == 1) return unit;
	if (y%2 == 1) {
		mat tmp = power(y-1);
		mul(tmp, unit);
		return tmp;
	}
	mat res = power(y/2);
	mul(res, res);
	return res;
}

int main() {
	ll n;
	int c;
	vector<int> V[26];
	bool one[26];
	memset(one, 0, sizeof one);
	cin >> n >> c;
	FOR(i, 0, c) {
		string s;
		int m;
		cin >> s >> m;
		if (m == 1)
			one[s[0]-'A'] = true;
		else
			V[s[0]-'A'].pb(m);
	}
	if (n == 0) {
		cout << 1 << endl;
		return 0;
	}
	int totone = 0;
	FOR(i, 0, 26) if (one[i]) totone++;
	sz = 0;
	lim = 1;
	FOR(i, 0, 26) if (!one[i]) FOR(j, 0, Size(V[i])) {
		bel[sz] = i;
		val[sz] = V[i][j];
		lim *= V[i][j];
		sz++;
	}
	FOR(i, 0, lim) FOR(j, 0, lim) {
		int A = i;
		int B = j;
		int sum[10];
		FOR(k, 0, sz) {
			sum[k] = (A%val[k] + B%val[k]) % val[k];
			A /= val[k];
			B /= val[k];
		}
		int C = 0;
		for (int k = sz-1; k >= 0; k--) {
			C *= val[k];
			C += sum[k];
		}
		table[i][j] = C;
	}

	FOR(i, 0, lim) unit.w[i] = 0;
	unit.w[0] = totone;

	int co[10];
	co[0] = 1;
	FOR(i, 0, sz) co[i+1] = co[i]*val[i];

	FOR(i, 0, sz) {
		int ind = 0;
		FOR(j, 0, sz) if (bel[i] == bel[j]) ind += co[j];
		unit.w[ind] = 1;
	}

	mat res = power(n);
	set<int> univ;
	FOR(i, 0, sz) univ.insert(bel[i]);
	int ans = 0;
	FOR(mask, 0, lim) {
		int dec[10];
		int tmp = mask;
		FOR(i, 0, sz) dec[i] = tmp%val[i], tmp /= val[i];
		set<int> sub;
		FOR(i, 0, sz) if (dec[i] == 0) sub.insert(bel[i]);
		if (sub == univ) ans = (ans+res.w[mask])%MOD;
	}
	cout << ans << endl;
	return 0;
}

// Believe in yourself...
#include<bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define F first
#define S second
#define sz(c) (c).size()
#define REP(i,n)  for(ll i=0;i<n;i++)
#define REPD(i,n) for(ll i=n-1;i>=0;i--)
#define FOR(i,a,b) for(ll i=a;i<=b;i++)
#define FORD(i,a,b) for(ll i=a;i>=b;i--)

#define bit(num,i) ((num>>i)&1)

using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;
typedef vector<vector<ll> > matrice;

const ll alpha=27;
const ll mod=12345;

#pragma GCC Optimize("Ofast")

vector<ll>v[alpha];
ll lc[alpha];
bool vis[alpha];
ll tot=1;
ll cnt[alpha];

void build_sq(matrice &mat,ll num){
	mat.resize(num);
	REP(i,num)
		mat[i].resize(num);
}

matrice operator*(matrice a,matrice b){
	matrice c;
	c.resize(sz(a));
	REP(i,sz(a))
		c[i].resize(sz(b));
	REP(i,sz(a)){
		REP(j,sz(b)){
			REP(k,sz(a[0])){
				c[i][j]=(c[i][j]+(a[i][k]*b[k][j]))%mod;
			}
		}
	}
	return c;
}

matrice Pow(matrice a,ll b){
	matrice ans;
	build_sq(ans,sz(a));
	REP(i,sz(a))
		ans[i][i]=1;
	while(b>0){
		if(b%2)
			ans=ans*a;
		a=a*a;
		b/=2;
	}
	return ans;
}

void decode(ll num){
	REP(i,alpha){
		if(!vis[i])continue;
		cnt[i]=num%lc[i];
		num/=lc[i];
	}
}
ll code(){
	ll num=0;
	REPD(i,alpha){
		if(!vis[i])continue;
		num*=lc[i];
		num+=cnt[i];
	}
	return num;
}

matrice build_transition(){
	matrice mat;
	build_sq(mat,tot);
	REP(codes,tot){
		decode(codes);
		REP(i,alpha){
			if(!vis[i])continue;
			cnt[i]=(cnt[i]-1+lc[i])%lc[i];
			mat[codes][code()]++;
			cnt[i]=(cnt[i]+1)%lc[i];
		}
	}
	return mat;
}
matrice build_begin(){
	matrice mat;
	mat.resize(1);
	mat[0].resize(tot);
	REP(i,tot){
		decode(i);
		bool yes=1;
		REP(j,alpha)
			yes&=(cnt[j]==0);
		mat[0][i]=yes;
	}
	return mat;
}

void print(matrice mat){
	REP(i,sz(mat)){
		REP(j,sz(mat[0]))
			cout<<mat[i][j]<<" ";
		cout<<endl;
	}
}
int main(){
	ll n,c;cin>>n>>c;
	REP(i,c){
		char ch;
		ll a,b;
		cin>>ch>>b;
		a=ch-'A';
		if(!vis[a]){
			vis[a]=1;
			lc[a]=1;
		}
		v[a].PB(b);
		lc[a]*=b;
		tot*=b;
	}
	matrice mat=build_begin()*Pow(build_transition(),n);
	ll ans=0;
	REP(i,tot){
		decode(i);
		bool final_yes=1;
		REP(j,alpha){
			if(!vis[j])continue;
			bool yes=0;
			REP(k,sz(v[j]))
				yes|=(cnt[j]%v[j][k]==0);
			if(!yes){
				final_yes=0;
				break;
			}
		}
		if(final_yes)
			ans=(ans+mat[0][i])%mod;
	}
	cout<<ans;
}

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

const int max_n = 131, mod = 12345;

long long n;
int m, C, cnt[max_n], l[max_n], r[max_n], num[max_n];
vector<int> v[max_n], v1;
map<vector<int>, int> q1;
map<int, vector<int> > q2;

void rec(int poz) {
    if (num[poz] == 0) {
        q1[v1] = C;
        q2[C] = v1;
        ++C;
        return;
    }
    int c = num[poz];
    for (int i = 0; i < v[c][poz - l[c]]; ++i) {
        v1[poz] = i;
        rec(poz + 1);
    }
}

struct matrix {
    vector<vector<int> > v;
    matrix() {
    }
    matrix(int n, int m) {
        v.resize(n, vector<int>(m, 0));
    }
    matrix operator * (const matrix &m) const {
        matrix res(v.size(), m.v[0].size());
        for (int i = 0; i < res.v.size(); ++i) {
            for (int j = 0; j < res.v[i].size(); ++j) {
                for (int k = 0; k < v[i].size(); ++k) {
                    res.v[i][j] += 1LL * v[i][k] * m.v[k][j];
                    res.v[i][j] %= mod;
                }
            }
        }
        return res;
    }
    void write(const string &s = "") const {
        for (int i = 0; i < v.size(); ++i) {
            for (int j = 0; j < v[i].size(); ++j) {
                cout << v[i][j] << " ";
            }
            cout << endl;
        }
    }
};

matrix power(matrix a, long long b) {
    matrix res(a.v.size(), a.v.size());
    for (int i = 0; i < res.v.size(); ++i) {
        res.v[i][i] = 1;
    }
    while (b) {
        if (b & 1) {
            res = res * a;
        }
        a = a * a;
        b >>= 1;
    }
    return res;
}

matrix A, B;

int main() {
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    cin >> n >> m;
    while (m--) {
        char c;
        int x;
        cin >> c >> x;
        v[c].push_back(x);
    }
    for (char c = 'A'; c <= 'Z'; ++c) {
        sort(v[c].begin(), v[c].end());
        v[c].erase(unique(v[c].begin(), v[c].end()), v[c].end());
        cnt[c] = cnt[c - 1] + v[c].size();
        l[c] = cnt[c - 1];
        r[c] = cnt[c] - 1;
        for (int i = l[c]; i <= r[c]; ++i) {
            num[i] = c;
            v1.push_back(0);
        }
    }
    rec(0);
    A = matrix(1, C);
    B = matrix(C, C);
    A.v[0][0] = 1;
    for (int i = 0; i < C; ++i) {
        v1 = q2[i];
        for (char c = 'A'; c <= 'Z'; ++c) {
            if (v[c].size()) {
                for (int j = l[c]; j <= r[c]; ++j) {
                    ++v1[j];
                    v1[j] %= v[c][j - l[c]];
                }
                int num = q1[v1];
                ++B.v[i][num];
                for (int j = l[c]; j <= r[c]; ++j) {
                    --v1[j];
                    v1[j] += v[c][j - l[c]];
                    v1[j] %= v[c][j - l[c]];
                }
            }
        }
    }
    B = power(B, n);
    A = A * B;
    int ans = 0;
    for (int i = 0; i < C; ++i) {
        v1 = q2[i];
        int f = 0;
        for (char c = 'A'; c <= 'Z'; ++c) {
            int ff = 0;
            for (int j = l[c]; j <= r[c]; ++j) {
                if (v1[j] == 0) {
                    ff = 1;
                    break;
                }
            }
            if (l[c] <= r[c] && ff == 0) {
                f = 1;
                break;
            }
        }
        if (f == 0) {
            ans = (ans + A.v[0][i]) % mod;
        }
    }
    cout << ans << endl;
    return 0;
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
#include <iomanip>
#include <set>
#include <map>
#include <queue>
#include <bitset>
#include <random>
#include <chrono>
#include <numeric>
typedef long long ll;
typedef long double ld;
using namespace std;

const ll mod = 12345;
vector<vector<ll> > multiply(vector<vector<ll> >& a, vector<vector<ll> >& b)
{
	int n = a.size();
	vector<vector<ll> > res(n, vector<ll>(n, 0));
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			for (int k = 0; k < n; k++)
			{
				res[i][j] += (a[i][k] * b[k][j]) % mod;
				res[i][j] %= mod;
			}
		}
	}
	return res;
}
vector<vector<ll> > pwr(vector<vector<ll> > a, ll b)
{
	if (b == 1)
	{
		return a;
	}
	vector<vector<ll> > half = pwr(a, (b >> 1));
	half = multiply(half, half);
	if (b & 1)
	{
		half = multiply(half, a);
	}
	return half;
}
const int crimes = 26;
vector<set<int> > laws(crimes);
vector<ll> prod(crimes, 0);
int from_state_to_num(vector<ll> com)
{
	int ans = 0;
	for (int i = 0; i < crimes; i++)
	{
		if (prod[i])
		{
			ans *= prod[i];
			ans += com[i];
		}
	}
	return ans;
}
vector<ll> from_num_to_state(int num)
{
	vector<ll> ans(crimes, 0);
	for (int i = crimes - 1; i >= 0; i--)
	{
		if (prod[i])
		{
			ans[i] = num % prod[i];
			num /= prod[i];
		}
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n;
	int c;
	cin >> n >> c;
	if (!n)
	{
		cout << 1 << "\n";
		return 0;
	}
	ll p = 1;
	for (int i = 0; i < c; i++)
	{
		char crime;
		int how_many;
		cin >> crime >> how_many;
		laws[crime - 'A'].insert(how_many);
		if (!prod[crime - 'A'])
		{
			prod[crime - 'A'] = 1;
		}
		prod[crime - 'A'] *= how_many;
		p *= how_many;
	}
	vector<vector<ll> > m(p, vector<ll>(p, 0));
	for (int i = 0; i < p; i++)
	{
		vector<ll> old = from_num_to_state(i);
		for (int j = 0; j < crimes; j++)
		{
			if (!prod[j])
			{
				continue;
			}
			vector<ll>nw = old;
			nw[j] = (nw[j] + 1) % prod[j];
			m[i][from_state_to_num(nw)]++;
		}
	}
	m = pwr(m, n);
	ll ans = 0;
	for (int i = 0; i < p; i++)
	{
		vector<ll> old = from_num_to_state(i);
		bool good = true;
		for (int j = 0; j < crimes; j++)
		{
			if (laws[j].size())
			{
				bool now = false;
				for (int k : laws[j])
				{
					if (old[j] % k == 0)
					{
						now = true;
					}
				}
				good &= now;
			}
		}
		if (good)
		{
			ans += m[0][i];
			ans %= mod;
		}
	}
	cout << ans << "\n";
	return 0;
}

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
#define mod 12345
using namespace std;

long long gcd(long long x,long long y) {
    if (x > y) swap(x,y);
    return (!x) ? y : gcd(y % x,x);
}

long long lcm(long long x,long long y) {
    return x/gcd(x,y) * y;
}

long long opt[26];
long long N;
char c[1005];
int req[1005];

int m;
vector<int> v,cur,candidate(26),active(26);
map< vector<int>,int > mp;
vector< vector<int> > store(205);
int total = 0;

struct matrix {
    int d[205][205];
};

matrix multiply(matrix A,matrix B) {
    matrix C;
    memset(C.d,0,sizeof(C.d));
    for (int k = 0; k < total; k++)
      for (int i = 0; i < total; i++)
        for (int j = 0; j < total; j++)
          C.d[i][j] = (C.d[i][j] + A.d[i][k] * B.d[k][j]) % mod;
    return C;
}

matrix power(matrix A,long long n) {
    int pos = 62;
    while ((n & (1LL << pos)) == 0) pos--;

    matrix ret;
    for (int i = 0; i < total; i++)
      for (int j = 0; j < total; j++) ret.d[i][j] = A.d[i][j];
    for (int i = pos - 1; i >= 0; i--) {
        ret = multiply(ret,ret);
        if (n & (1LL << i)) ret = multiply(ret,A);
    }
    return ret;
}

void attempt(int idx) {
    if (idx >= v.size()) {
        mp[cur] = total;
        store[total] = cur;
        total++;
        return;
    }
    for (int i = 0; i < v[idx]; i++) {
        cur[idx] = i;
        attempt(idx + 1);
    }
}

int main() {
//    freopen("d.in.1","r",stdin);
    cin >> N >> m;
    if (N == 0) {
        printf("1\n");  return 0;
    }

    for (int i = 0; i < 26; i++) opt[i] = 1;
    for (int i = 0; i < m; i++) {
        while (1) {
            scanf("%c", &c[i]);
            if ('A' <= c[i] && c[i] <= 'Z') break;
        }
        c[i] -= 'A';
        active[c[i]] = true;
        scanf("%d", &req[i]);
        opt[c[i]] = lcm(opt[c[i]],req[i]);
    }
    for (int i = 0; i < 26; i++) if (active[i]) {
        v.push_back(opt[i]);
        candidate[i] = v.size() - 1;
    }
    cur.resize(v.size());
    attempt(0);

    matrix alpha;
    memset(alpha.d,0,sizeof(alpha.d));
    for (int i = 0; i < total; i++)
      for (int j = 0; j < v.size(); j++) {
          vector<int> tmp = store[i];
          tmp[j] = (tmp[j] + 1) % v[j];
          alpha.d[mp[tmp]][i]++;
      }

    alpha = power(alpha,N);
    int ret = 0;
    for (int i = 0; i < total; i++) {
        bool ok[26];
        memset(ok,false,sizeof(ok));
        vector<int> tmp = store[i];
        for (int j = 0; j < m; j++) if (tmp[candidate[c[j]]] % req[j] == 0) ok[candidate[c[j]]] = true;
        bool flag = true;
        for (int j = 0; j < v.size(); j++) if (!ok[j]) flag = false;
        if (flag) ret = (ret + alpha.d[0][i]) % mod;
    }
    printf("%d\n", ret);
}

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <cmath>
#include <vector>
#include <set>
#include <map>
#include <unordered_set>
#include <unordered_map>
#include <queue>
#include <ctime>
#include <cassert>
#include <complex>
#include <string>
#include <cstring>
#include <chrono>
#include <random>
#include <bitset>
using namespace std;

#ifdef LOCAL
	#define eprintf(...) fprintf(stderr, __VA_ARGS__);fflush(stderr);
#else
	#define eprintf(...) 42
#endif

using ll = long long;
using ld = long double;
using uint = unsigned int;
using ull = unsigned long long;
template<typename T>
using pair2 = pair<T, T>;
using pii = pair<int, int>;
using pli = pair<ll, int>;
using pll = pair<ll, ll>;
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
ll myRand(ll B) {
	return (ull)rng() % B;
}

#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()
#define fi first
#define se second

clock_t startTime;
double getCurrentTime() {
	return (double)(clock() - startTime) / CLOCKS_PER_SEC;
}

const ll MOD = 12345;
ll add(ll x, ll y) {
	x += y;
	if (x >= MOD) return x - MOD;
	return x;
}
ll sub(ll x, ll y) {
	x -= y;
	if (x < 0) return x + MOD;
	return x;
}
ll mult(ll x, ll y) {
	return (x * y) % MOD;
}
ll bin_pow(ll x, ll p) {
	if (p == 0) return 1;
	if (p & 1) return mult(x, bin_pow(x, p - 1));
	return bin_pow(mult(x, x), p / 2);
}
ll rev(ll x) {
	return bin_pow(x, MOD - 2);
}

const int L = 61;
const int A = 26;
const int N = 144;
vector<int> z[A];
vector<int> b[A];
int h[A];
ll M[L][N][N];
ll w[2][N];

bool isGood(int x) {
	for (int c = 0; c < A; c++) {
		if (h[c] == -1) continue;
		int y = x % (int)b[c].size();
		x /= (int)b[c].size();
		if (b[c][y] == 0) return false;
	}
	return true;
}

int main()
{
	startTime = clock();
//	freopen("input.txt", "r", stdin);
//	freopen("output.txt", "w", stdout);

	ll n;
	int m;
	scanf("%lld%d", &n, &m);
	while(m--) {
		char t;
		int w;
		scanf(" %c %d", &t, &w);
		int c = (int)(t - 'A');
		z[c].push_back(w);
	}
	for (int c = 0; c < A; c++) {
		if (z[c].empty()) continue;
		int L = 1;
		for (int x : z[c]) L = lcm(L, x);
		b[c] = vector<int>(L, 0);
		for (int x : z[c]) {
			for (int i = 0; i < L; i += x)
				b[c][i] = 1;
		}
	}
	int S = 1;
	for (int c = 0; c < A; c++) {
		h[c] = -1;
		if (b[c].empty()) continue;
		h[c] = S;
		S *= (int)b[c].size();
	}
	assert(S < N);
	for (int x = 0; x < S; x++) {
		for (int c = 0; c < A; c++) {
			if (h[c] == -1) continue;
			int y = (x / h[c]);
			y %= (int)b[c].size();
			if (y + 1 == (int)b[c].size()) {
				y = x - h[c] * ((int)b[c].size() - 1);
			} else {
				y = x + h[c];
			}
			M[0][x][y]++;
		}
	}
	for (int k = 0; k + 1 < L; k++) {
		for (int i = 0; i < S; i++)
			for (int j = 0; j < S; j++) {
				M[k + 1][i][j] = 0;
				for (int h = 0; h < S; h++)
					M[k + 1][i][j] = add(M[k + 1][i][j], mult(M[k][i][h], M[k][h][j]));
			}
	}
	w[0][0] = 1;
	for (int k = 0; k < L; k++) {
		if (((n >> k) & 1) == 0) continue;
		for (int i = 0; i < S; i++)
			w[1][i] = 0;
		for (int i = 0; i < S; i++)
			for (int j = 0; j < S; j++)
				w[1][j] = add(w[1][j], mult(w[0][i], M[k][i][j]));
		for (int i = 0; i < S; i++)
			w[0][i] = w[1][i];
	}
	ll ans = 0;
	for (int x = 0; x < S; x++)
		if (isGood(x))
			ans = add(ans, w[0][x]);
	printf("%lld\n", ans);

	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
const int P=12345;
const int maxn=130;
int N,A[maxn];LL n;
bool B[maxn][maxn];

struct Tmtx{
	int a[maxn][maxn];int n;
	Tmtx(){}
	Tmtx(int _n,bool x=0){
		int i;n=_n,memset(a,0,sizeof a);
		for(i=0;i<n;++i)a[i][i]=x;
	}
	Tmtx Tpose()const{
		Tmtx b;register int i,j;
		for(i=0;i<n;++i)
		for(j=0;j<n;++j)b.a[i][j]=a[j][i];
		return b;
	}
	Tmtx operator *(const Tmtx &b)const{
		Tmtx c(n,0);register int k,i,j;
		for(i=0;i<n;++i)
		for(j=0;j<n;++j)
		for(k=0;k<n;++k)
			c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%P;
		return c;
	}
	bool operator ==(const Tmtx &b)const{
		register int i,j;
		for(i=0;i<n;++i)
		for(j=0;j<n;++j)
			if(a[i][j]!=b.a[i][j])return false;
		return true;
	}
	void print(){
		int i,j;
		for(i=0;i<n;++i){
			for(j=0;j<n;++j)cerr<<a[i][j]<<' ';
			cerr<<endl;
		}
	}
};
Tmtx pow(Tmtx x,LL k){
	Tmtx Fc=Tmtx(x.n,1);
	for(;k;k>>=1)k&1?Fc=Fc*x:0,x=x*x;
	return Fc;
}

namespace Ninit{
	char s[10];
	void init(){
		int ni,ai,i,j;
		cin>>n>>ni;
		for(i=0;i<26;++i)A[i]=1;
		for(i=0;i<ni;++i){
			scanf("%s%d",s,&ai),A[s[0]-'A']*=ai;
			for(j=0;j<123;++j)B[s[0]-'A'][j]|=(j%ai==0);
		}
	}
}

namespace Nsolve{
	Tmtx An,A0;
	int pw[maxn],ans;
	void solve(){
		int i,j,k,xi,flag;
		for(pw[0]=1,i=1;i<=26;++i)pw[i]=pw[i-1]*A[i-1];
		An.n=A0.n=N=pw[26];
		for(i=0;i<N;++i){
			for(k=0;k<26;++k)if(B[k][0]){
				xi=i/pw[k]%A[k];
				++A0.a[i][i-xi*pw[k]+(xi+1)%A[k]*pw[k]];
			}
		}
		An=pow(A0,n);
		//A0.print();An.print();
		for(i=0;i<N;++i){
			for(flag=0,k=0;k<26;++k){
				if(!B[k][0])continue;
				if(!B[k][i/pw[k]%A[k]])flag=1;
			}
			if(!flag)ans=(ans+An.a[0][i])%P;
		}
		cout<<ans<<endl;
	}
}

int main(){
	//freopen("A.in","r",stdin);
	Ninit::init();
	Nsolve::solve();
	return 0;
}

#define _CRT_SECURE_NO_DEPRECATE
#pragma comment(linker, "/STACK:64000000")

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <utility>
#include <memory.h>
#include <cstring>

#include <set>
#include <map>
#include <vector>
#include <string>
#include <queue>

#include <iostream>
#include <sstream>

using namespace std;

typedef long long int64;

#define forn(i, n) for(int i = 0; i < (int)(n); i++)
#define ford(i, n) for(int i = (int)(n) - 1; i >= 0; i--)
#define pb push_back
#define mp make_pair
#define all(a) a.begin(), a.end()

const int INF = (int)1E9;
const int64 INF64 = (int64)1E18;
const long double EPS = 1E-8;
const long double PI = 3.1415926535897932384626433832795;

const int MAXN = 150;
const int MOD = 12345;

void mult(int a[MAXN][MAXN], int b[MAXN][MAXN]) {
    int res[MAXN][MAXN];
    memset(res, 0, sizeof res);

    forn(i, MAXN)
        forn(j, MAXN)
            forn(k, MAXN)
                res[i][j] = (res[i][j] + a[i][k] * b[k][j]) % MOD;

    memcpy(a, res, sizeof res);
}

void bpow(int a[MAXN][MAXN], int64 b) {
    int res[MAXN][MAXN];
    memset(res, 0, sizeof res);
    forn(i, MAXN) res[i][i] = 1;

    while (b > 0)
        if (b % 2 == 0) {
            mult(a, a);
            b /= 2;
        } else {
            mult(res, a);
            b--;
        }

    memcpy(a, res, sizeof res);
}

int n, len[1200], mul[1200], m[MAXN][MAXN];
vector<int> g[30];

void IntToArray(int v, int * a) {
    ford(i, n) {
        a[i] = v / mul[i];
        v %= mul[i];
    }
}

int ArrayToInt(int * a) {
    int ans = 0;
    forn(i, n)
        ans += a[i] * mul[i];
    return ans;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "wt", stdout);
#endif

    int64 p;
    cin >> p >> n;
    forn(i, n) {
        char c;
        scanf(" %c%d", &c, &len[i]);
        g[c - 'A'].pb(i);

        if (i == 0)
            mul[i] = 1;
        else
            mul[i] = mul[i - 1] * len[i - 1];
    }

    mul[n] = mul[n - 1] * len[n - 1];
    forn(v, 26) {
        if (g[v].empty()) continue;

        forn(mask, mul[n]) {
            int a[1200];
            IntToArray(mask, a);

            forn(i, g[v].size()) {
                int pos = g[v][i];
                a[pos] = (a[pos] + 1) % len[pos];
            }

            m[mask][ArrayToInt(a)]++;
        }
    }

    bpow(m, p);

    int ans = 0;
    if (p == 0 && n == 0) ans = 1;
    forn(mask, mul[n]) {
        int a[1200];
        IntToArray(mask, a);

        bool ok = true;
        forn(v, 26) {
            bool ok1 = g[v].empty();
            forn(i, g[v].size()) {
                int pos = g[v][i];
                if (a[pos] == 0) ok1 = true;
            }

            ok &= ok1;
        }

        if (ok) ans = (ans + m[0][mask]) % MOD;
    }

    cout << ans << endl;

    return 0;
}

// Problem : D. Crime Management
// Contest : Codeforces - Codeforces Beta Round #83 (Div. 1 Only)
// URL : https://codeforces.com/problemset/problem/107/D
// Memory Limit : 256 MB
// Time Limit : 5000 ms
// Powered by CP Editor (https://github.com/cpeditor/cpeditor)

#include <bits/stdc++.h>

using namespace std;

long long E, M, N;
const long long MOD = 12345;
int base[30];
set<int> st;
vector<int> lst[30];

struct Matrix{
	vector<vector<long long>> mat;
	int r, c;

	Matrix(){
		r = c = 0;
	}

	Matrix(int _r, int _c){
		r = _r, c = _c;
		mat.resize(_r);
		for(int i = 0; i<_r; i++){
			mat[i].resize(_c, 0);
		}
	}

	Matrix operator + (const Matrix & m){
		Matrix ret(r, c);
		for(int i = 0; i<r; i++){
			for(int j = 0; j<c; j++){
				ret.mat[i][j] = mat[i][j] + m.mat[i][j];
				ret.mat[i][j] %= MOD;
			}
		}
		return ret;
	}

	Matrix operator - (const Matrix & m){
		Matrix ret(r, c);
		for(int i = 0; i<r; i++){
			for(int j = 0; j<c; j++){
				ret.mat[i][j] = mat[i][j] - m.mat[i][j];
				ret.mat[i][j] %= MOD;
				ret.mat[i][j] += MOD;
				ret.mat[i][j] %= MOD;
			}
		}
		return ret;
	}

	Matrix operator * (const Matrix & m){
		Matrix ret(r, m.c);
		for(int i = 0; i<r; i++){
			for(int j = 0; j<m.c; j++){
				for(int k = 0; k<c; k++){
					ret.mat[i][j] += mat[i][k] * m.mat[k][j];
				}
				ret.mat[i][j] %= MOD;
			}
		}
		return ret;
	}
};

Matrix graph;

Matrix qikpow(long long e){
	if(!e){
		Matrix ret(N, N);
		for(int i = 0; i<N; i++){
			ret.mat[i][i] = 1;
		}
		return ret;
	}
	Matrix ret = qikpow(e/2);
	ret = ret*ret;
	if(e&1){
		ret = ret*graph;
	}
	/*
	cout << e << "\n";
	for(int i = 0; i<N; i++){
		for(int j = 0; j<N; j++){
			cout << ret.mat[i][j];
		}
		cout << "\n";
	}
	*/
	return ret;
}

int main(){
	ios::sync_with_stdio(0);
	cin.tie(0);
	cout.tie(0);
	cin >> E >> M;
	fill(base, base+26, 1);
	while(M--){
		char c;
		int m;
		cin >> c >> m;
		int k = c-'A';
		base[k] = base[k] * m / __gcd(base[k], m);
		lst[k].push_back(m);
		st.insert(k);
	}
	N = 1;
	for(int i = 0; i<26; i++){
		N *= base[i];
	}
	graph = Matrix(N, N);
	for(int i = 0; i<N; i++){
		for(int n : st){
			//cout << "bing: " << i << " " << n << "\n";
			int t = i;
			for(int b = 0; b<n; b++){
				t /= base[b];
			}
			int v = t%base[n];
			int w = v;
			v++;
			v %= base[n];
			//cout << n << " " << v << "\n";
			for(int b = 0; b<n; b++){
				v *= base[b];
				w *= base[b];
			}
			int j = i+v-w;
			//cout << i << " " << j << " " << N << "\n";
			graph.mat[i][j]++;
		}
	}
	/*
	for(int i = 0; i<N; i++){
		for(int j = 0; j<N; j++){
			cout << graph.mat[i][j];
		}
		cout << "\n";
	}
	*/
	Matrix ret = qikpow(E);
	long long ans = 0;
	for(int i = 0; i<N; i++){
		bool good = 1;
		for(int n : st){
			bool chk = 0;
			int t = i;
			for(int b = 0; b<n; b++){
				t /= base[b];
			}
			int v = t%base[n];
			for(int d : lst[n]){
				if(v%d == 0){
					chk = 1;
				}
			}
			good &= chk;
		}
		if(good){
			ans += ret.mat[0][i];
		}
	}
	cout << ans%MOD;
}

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int mod=12345;
struct node{int mart[150][150];}a,b;
int I,m,cnt,p[505],mp[505],base[505];
char s1;long long n;vector<int>ch[505];
node operator *(node a,node b)
{
	node c;memset(c.mart,0,sizeof c.mart);
	for(int i=0;i<=I;i++)for(int j=0;j<=I;j++)for(int k=0;k<=I;k++)
	(c.mart[i][j]+=a.mart[i][k]*b.mart[k][j])%=mod;return c;
}
bool check(int s)
{
	for(int i=1;i<=cnt;i++)
	{
		int flag=0;
		for(int j=0;j<ch[i].size()&&!flag;j++)
		{if((s/base[i-1]%p[i])%ch[i][j]==0)flag=1;}
		if(!flag)return 0;
	}
	return 1;
}
int main()
{
	scanf("%I64d%d",&n,&m);I=1;
	for(int i=1,s,lim;i<=m;i++)
	{
		scanf("%1s%d",&s1,&lim);s=static_cast<int>(s1);
		if(!mp[s])mp[s]=++cnt,p[mp[s]]=1;p[mp[s]]*=lim;
		ch[mp[s]].push_back(lim);I*=lim;
	}
	I--;base[0]=1;for(int i=1;i<=cnt;i++)base[i]=base[i-1]*p[i];
	for(int i=0;i<=I;i++)
	{
		for(int j=1;j<=cnt;j++)
		{
			int nw=i/base[j-1]%p[j],nx=(nw+1)%p[j];
			(b.mart[i][i+(nx-nw)*base[j-1]]+=1)%=mod;
		}
	}
	a.mart[0][0]=1;int ans=0;
	for(;n;n>>=1,b=b*b)if(n&1)a=a*b;
	for(int i=0;i<=I;i++)if(check(i))(ans+=a.mart[0][i])%=mod;
	printf("%d\n",ans);
}

//#pragma comment(linker,"/STACK:256000000")

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <queue>
#include <stack>
#include <bitset>
#include <algorithm>
#include <functional>
#include <numeric>
#include <utility>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cmath>
#include <ctime>
#include <cassert>
#include <stdio.h>
#include <string>
#include <memory.h>

using namespace std;

#define ldb long double
#define LL long long
#define nextline() {int c; while ((c = getchar()) != 10 && c != EOF);}

#define PI 3.1415926535897932384626433832795
#define EPS 1e-9

#define sqr(x) ((x) * (x))
#define ABS(a) ((a)<0?-(a):(a))
#define EQ(a,b) (ABS((a)-(b))<EPS)

#define all(a) a.begin(), a.end()
#define two(i) (1 << (i))
#define has(mask, i) ((((mask) & two(i)) == 0) ? false : true)

const int INF = 1000 * 1000 * 1000;
const LL INF64 = 1000LL * 1000LL * 1000LL * 1000LL * 1000LL * 1000LL;

const int MOD = 12345;

LL N;
int a[125][125];
int b[125][125];
int c[125][125];
int e[125][125];

int mul[30];
int can[30];
vector <int> mm[30];

void Load()
{
	for (int i = 0; i < 26; i++)
		mul[i] = 1;

	cin >> N;

	int m;

	cin >> m;

	string s;
	int x;

	for (int i = 1; i <= m; i++)
	{
		cin >> s >> x;
		mm[s[0] - 'A'].push_back (x);
		mul[s[0] - 'A'] *= x;
		can[s[0] - 'A'] = 1;
	}
}

map <vector <int>, int> mp;
vector <vector <int> > q;

vector <int> v, cur;

void Solve()
{
	int m = 0;

	for (int i = 0; i < 26; i++)
		v.push_back(0);

	q.push_back(v);
	mp[v] = m;

	int head = 0;
	while (head < (int)q.size())
	{
		v = q[head++];
		for (int i = 0; i < 26; i++)
			if (can[i])
			{
				cur = v;
				cur[i]++;
				cur[i] %= mul[i];
				if (mp.find(cur) == mp.end())
				{
					m++;
					mp[cur] = m;
					q.push_back(cur);
				}
			}
	}

	int n = (int)q.size();

	for (int i = 0; i < n; i++)
		for (int j = 0; j < 26; j++)
			if (can[j])
			{
				v = q[i];
				v[j]++;
				v[j] %= mul[j];
				a[i][mp[v]]++;
			}

	for (int i = 0; i < n; i++)
		e[i][i] = 1;

	while (N > 0)
	{
		if (N & 1)
		{
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++)
				{
					c[i][j] = 0;
					for (int k = 0; k < n; k++)
						c[i][j] = (c[i][j] + e[i][k] * a[k][j]) % MOD;
				}
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++)
					e[i][j] = c[i][j];
			N--;
		}
		else
		{
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++)
				{
					c[i][j] = 0;
					for (int k = 0; k < n; k++)
						c[i][j] = (c[i][j] + a[i][k] * a[k][j]) % MOD;
				}
			for (int i = 0; i < n; i++)
				for (int j = 0; j < n; j++)
					a[i][j] = c[i][j];
			N >>= 1;
		}
	}

	v.assign(n, 0);

	for (int i = 0; i < n; i++)
		v[i] = e[0][i];

	int ans = 0;

	for (int i = 0; i < n; i++)
	{
		bool fl = true;
		for (int j = 0; j < 26; j++)
			if (can[j])
			{
				bool ok = false;
				for (int t = 0; t < (int)mm[j].size(); t++)
					if (q[i][j] % mm[j][t] == 0)
						ok = true;

				fl = min (fl, ok);
			}
		if (fl)
			ans = (ans + v[i]) % MOD;
	}

	cout << ans;
}

int main()
{
	//ios_base::sync_with_stdio(0);
#ifndef ONLINE_JUDGE
	freopen("in", "rt", stdin);
	freopen("out", "wt", stdout);
#endif
	Load();
	Solve();
	return 0;
}

/*
 * 2011-08-23  Martin  <Martin@Martin-desktop>

 *
 */
#include <algorithm>
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>

using namespace std;

#define tr(i, x) for (typeof(x.begin()) i = x.begin(); i != x.end(); ++ i)
#define rep(i, n) for (int i = 0; i < n; ++ i)
#define pii pair <int, int>
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define ll long long

#define CharSet 26
#define Mod 12345

class Matrix: public vector < vector <int> >
{
	private:
		Matrix(int n, vector <int> a)
		{
			this->clear();
			rep (i, n)
				pb(a);
		}
	public:
		Matrix()
		{
			this->clear();
		}
		Matrix(int n, int m)
		{
			this->clear();
			*this = Zero(n, m);
		}
		Matrix Zero(int n, int m)
		{
			return Matrix (n, vector <int> (m, 0));
		}
		Matrix One(int n)
		{
			Matrix res(n, n);
			rep (i, n)
				res[i][i] = 1;
			return res;
		}
		Matrix operator * (const Matrix &b)
		{
			Matrix c;
			if (rows() == b.lines())
			{
				int u = lines();
				int v = rows();
				int w = b.rows();
				c = Zero(u, w);
				rep (i, u)
					rep (j, v)
						rep (k, w)
						{
							c[i][k] += (*this)[i][j] * b[j][k];
							c[i][k] %= Mod;
						}
			}
			else
				cerr << "error occurred at " << __LINE__ << endl;
			return c;
		}
		Matrix pow(ll n)
		{
			Matrix res;
			if (lines() == rows())
			{
				int l = lines();
				res = res.One(l);
				Matrix tmp(*this);
				for (int i = 0; (n >> i) > 0; ++ i)
				{
					if ((n & (1LL << i)) > 0)
						res = res * tmp;
					tmp = tmp * tmp;
				}
			}
			else
				cerr << "error occurred at " << __LINE__ << endl;
			return res;
		}
		size_type lines() const
		{
			return size();
		}
		size_type rows() const
		{
			return (size() == 0) ? 0 : (*this)[0].size();
		}
};

ll N;
int C;
bool Appear[CharSet], isOne[CharSet];

int main()
{
	cin >> N >> C;
	fill(Appear, Appear + CharSet, 0);
	fill(isOne, isOne + CharSet, 0);
	vector <pii> cd;
	cd.clear();
	rep (i, C)
	{
		char Ch;
		int t;
		cin >> Ch >> t;
		Appear[Ch - 'A'] = 1;
		if (t != 1)
			cd.pb(mp(Ch - 'A', t));
		else
			isOne[Ch - 'A'] = 1;
	}
	vector <int> pd;
	pd.clear();
	int cds = cd.size();
	pd.pb(1);
	rep (i, cds)
		pd.pb(pd.back() * cd[i].y);
	int matsize = pd.back();
	Matrix mat(matsize, matsize);
	rep (i, matsize)
	{
		rep (ch, 26)
			if (Appear[ch])
			{
				int target = i;
				rep (k, cds)
					if (cd[k].x == ch)
					{
						if ((target % pd[k + 1]) / pd[k] == cd[k].y - 1)
							target -= (cd[k].y - 1) * pd[k];
						else
							target += pd[k];
					}
				++ mat[i][target];
			}
	}
	mat = mat.pow(N);
	ll ans = 0;
	rep (i, matsize)
	{
		bool Flag = 1;
		rep (ch, 26)
			if (Appear[ch] && !isOne[ch])
			{
				bool Satisfy = 0;
				bool Exist = 0;
				rep (k, cds)
					if (cd[k].x == ch)
					{
						Exist = 1;
						if ((i % pd[k + 1]) / pd[k] == 0)
							Satisfy = 1;
					}
				if (Exist && !Satisfy)
				{
					Flag = 0;
					break;
				}
			}
		if (Flag)
			ans = (ans + mat[0][i]) % Mod;
	}
	cout << ans << endl;
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define ll long long
struct matrix {
  int v[200][200];
  int row, col;
};
int mod = 12345;
matrix multiply(matrix a, matrix b) {
  assert(a.col == b.row);
  matrix r;
  r.row = a.row;
  r.col = b.col;
  for (int i = 0; i < r.row; i++) {
    for (int j = 0; j < r.col; j++) {
      int sum = 0;
      for (int k = 0; k < a.col;  k++) {
        sum += a.v[i][k] * b.v[k][j];
        sum %= mod;
      }
      r.v[i][j] = sum;
    }
  }
  return r;
}
matrix powe(matrix mat, ll p) {
//cout<<p<<endl;
  assert(p >= 1);
 // cout<<p<<endl;
  if (p == 1) return mat;
  if (p % 2 == 1)
    return multiply(mat, powe(mat, p - 1));
  matrix ret = powe(mat, p / 2);
  ret = multiply(ret, ret);
  return ret;
}
map<vector<int>,int>name;
map<vector<int>,int>::iterator it;
vector<int>tp,my[27];
int tot;
int intact[800],val[800];

void name_it(int pos,vector<int>&vc)
{
    if(pos==tp.size())
    {
       name[vc]=tot++;
      // cout<<tot
      // for(int i=0;i<vc.size();i++)cout<<vc[i]<<" ";
      // cout<<endl;
       {
          for(int j=0;j<tp.size();j++)
          {
              int g=tp[j];
              for(int k=0;k<my[g].size();k++)
              {
                  if(vc[j]%my[g][k]==0)intact[tot-1]++;
                  if(vc[j]%my[g][k]==0)break;
              }
          }

       }
       return ;
    }
    int g=tp[pos];
    for(int i=0;i<val[g];i++)
    {
        vc[pos]=i;
        name_it(pos+1,vc);
    }
}
int bigmod(int x,ll p)
{
   if(p==1)return x;
   if(p&1)
   {
      return x*bigmod(x,p-1)%mod;
   }
   int g=bigmod(x,p/2);
   return g*g%mod;
}
int main()
{
    char str[5];
    ll n;
    int q;
    cin>>n>>q;
    for(int i=0;i<q;i++)
    {
         int l;
         scanf("%s%d",str,&l);
         my[str[0]-65].pb(l);
    }
   // cout<<"dsd"<<endl;
    int cnt=0;
    for(int i=0;i<26;i++)
    {
        if(my[i].size()==0)continue;
        int lcm=1;
        for(int j=0;j<my[i].size();j++)
        {

              lcm=(lcm*my[i][j])/__gcd(lcm,my[i][j]);
              if(my[i][j]==1){lcm=1;break;}
        }
        if(lcm==1)cnt++;
        else {
          tp.pb(i);
          val[i]=lcm;
        }
    }
   // cout<<"sfd"<<endl;
    if(n==0)
    {
       cout<<"1"<<endl;
       return 0;
    }
    if(tp.size()==0)
    {
       ll ans=bigmod(cnt,n);
       cout<<ans<<endl;
       return 0;
    }
    vector<int>lagbe;
    lagbe.resize(tp.size());
    name_it(0,lagbe);
  //  cout<<"df"<<endl;
  //cout<<cnt<<endl;
    matrix ans;
    memset(ans.v,0,sizeof ans.v);
    ans.row=tot;
    ans.col=tot;
    for(it=name.begin();it!=name.end();it++)
    {
        int g=it->second;
        ans.v[g][g]=cnt;
        vector<int>tmp=it->first;
        for(int j=0;j<tmp.size();j++)
        {
            vector<int>jargon=tmp;
            jargon[j]+=1;
            jargon[j]%=val[tp[j]];
         //   assert(name.find(jargon)!=name.end());
            int rs=name[jargon];
            ans.v[g][rs]=1;
        }
    }
    //cout<<tot<<" "<<cnt<<endl;
 //   cout<<"sdf"<<endl;
 //cout<<n<<endl;
    ans=powe(ans,n);
  //  cout<<"sdf"<<endl;
    int ou=0;
    for(int i=0;i<tot;i++)
    {
        if(intact[i]!=(int)tp.size())continue;
       // cout<<"sdf"<<endl;
        ou+=ans.v[0][i];
    }
    ou%=mod;
    cout<<ou<<endl;

}

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MEM(a,b) memset((a),(b),sizeof(a))
const LL INF = 12345;
const int N = 2e2 + 10;
class Matrix
{
	int a[N][N];
	int n;
public:
	Matrix ones(int n)
	{
		Matrix ret(n);
		for (int i = 0; i < n; i++) ret[i][i] = 1;
		return ret;
	}
	Matrix(int n = 0)
	{
		init(n);
	}
	void init(int n)
	{
		this->n = n;
		MEM(a, 0);
	}
	int* operator [] (int i)
	{
		return a[i];
	}
	Matrix operator + (Matrix &m)
	{
		Matrix ret(*this);
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				a[i][j] += m[i][j];
				if (a[i][j] >= INF) a[i][j] -= INF;
			}

		}
	}
	Matrix operator *(Matrix &m)
	{
		Matrix ret(n);
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					ret[i][j] = (ret[i][j] + 1LL * a[i][k] * m[k][j]) % INF;
				}
			}
		}
		return ret;
	}
	Matrix operator ^(LL b)
	{
		Matrix ret = ones(n);
		Matrix a = *this;
		while (b)
		{
			if (b & 1) ret = ret * a;
			a = a * a;
			b >>= 1;
		}
		return ret;
	}
};
int gcd(int n, int m)
{
	return m == 0 ? n : gcd(m, n%m);
}
int v[N];
int a[N];
int w[N];
int flag[N][N];
int key[N];
int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	map<char, int> mc;
	LL n;
	int m;
	cin >> n >> m;
	vector<pair<char, int>> vp;
	int tot = 1;
	for (int i = 0; i < m; i++)
	{
		char c;
		int x;
		cin >> c >> x;
		mc[c] = 1;
		flag[c][x] = 1;
	}
	for (int i = 'A'; i <= 'Z'; i++)
	{
		int cur = 1;
		for (int j = 1; j < N; j++)
		{
			if (flag[i][j] == 0) continue;
			for (int k = j + j; k < N; k += j) flag[i][k] = 0;
			cur *= j;
			if (vp.empty() || vp.back().first != i) vp.push_back({ i,cur });
			else vp.back().second = cur;
			tot *= j;
		}
		for (int j = 1; j < N; j++)
		{
			if (flag[i][j] == 0) continue;
			for (int k = j; k < N; k += j) flag[i][k] = 1;
			flag[i][0] = 1;
		}
	}
	int sz = 0;
	for (auto &p : vp) v[sz++] = p.second;
	v[sz] = 1;
	w[0] = 1;
	for (int i = 1; i < sz; i++) w[i] = v[i - 1] * w[i - 1];
	vector<int> ans;
	for (int i = 0; i < tot; i++)
	{
		MEM(key, 0);
		int cur = i;
		for (int j = 0; j < sz; j++)
		{
			int x = cur % v[j];
			cur /= v[j];
			if (flag[vp[j].first][x])
				key[vp[j].first] = 1;
		}
		if (count(key, key + N, 1) == mc.size()) ans.push_back(i);
	}
	Matrix b(tot);
	for (int i = 0; i < tot; i++)
	{
		int cur = i;
		for (int j = 0; j < sz; j++)
		{
			int x = cur % v[j];
			cur /= v[j];
			int y = (x + 1) % v[j];
			b[i][i - (x - y)*w[j]]++;
		}
	}
	b = b ^ n;
	int ret = 0;
	for (auto &x : ans)
	{
		ret += b[0][x];
		if (ret >= INF) ret -= INF;
	}
	printf("%d\n", ret);
	return 0;
}

#include <iostream>
#include <cstring>
#include <cstdio>
#include <vector>
#define pb push_back
#define MOD 12345
using namespace std;
typedef long long ll;
struct Matrix
{
	int arr[125][125], n;
	Matrix(int _n = 0)
	{
		n = _n;
		memset(arr, 0, sizeof(arr));
	}
	inline Matrix operator *(const Matrix &a) const
	{
		Matrix res(n);
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
					res.arr[i][j] = (res.arr[i][j] + arr[i][k] * a.arr[k][j]) % MOD;
			}
		}
		return res;
	}
	inline Matrix operator *=(const Matrix &a)
	{
		return *this = *this * a;
	}
};
inline Matrix quick_pow(Matrix a, ll n)
{
	Matrix res(a.n);
	res.arr[0][0] = 1;
	while (n)
	{
		if (n & 1)
			res *= a;
		a *= a;
		n >>= 1;
	}
	return res;
}
int arr[35], coef[35];
vector<int> mul[35];
bool vis[35];
inline int gcd(int x, int y)
{
	int r;
	while (y)
	{
		r = x % y;
		x = y;
		y = r;
	}
	return x;
}
int main()
{
	// freopen("107D.in", "r", stdin);
	ll t;
	int n;
	scanf("%lld%d", &t, &n);
	for (int i = 0; i < 26; i++)
		arr[i] = 1;
	for (int i = 0; i < n; i++)
	{
		char c;
		int x;
		scanf("%*c%c%d", &c, &x);
		arr[c - 'A'] *= x;
		mul[c - 'A'].pb(x);
		vis[c - 'A'] = true;
	}
	int cur = 1;
	for (int i = 0; i < 26; i++)
	{
		coef[i] = cur;
		cur *= arr[i];
	}
	Matrix mat(cur);
	for (int i = 0; i < cur; i++)
	{
		for (int j = 0; j < 26; j++)
		{
			if (!vis[j])
				continue;
			int x = i / coef[j] % arr[j];
			mat.arr[i][i + ((x + 1) % arr[j] - x) * coef[j]]++;
		}
	}
	Matrix res = quick_pow(mat, t);
	int ans = 0;
	for (int i = 0; i < cur; i++)
	{
		bool g = true;
		for (int j = 0; j < 26 && g; j++)
		{
			if (!vis[j])
				continue;
			int x = i / coef[j] % arr[j];
			bool f = false;
			for (auto y : mul[j])
			{
				if (!(x % y))
					f = true;
			}
			if (!f)
				g = false;
		}
		if (g)
			ans = (ans + res.arr[0][i]) % MOD;
	}
	printf("%d\n", ans);
	return 0;
}

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef __int64 LL;
const int mod=12345;
const int N=130;
vector<int> ve[30];
#define pb push_back
int top,ww[N],sta[N];
int ll[30],rr[30];

void cp(int A[N][N],int B[N][N],int n){
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            A[i][j]=B[i][j];
        }
    }
}

int D[N][N];
void _mul(int A[N][N],int B[N][N],int n){
    memset(D,0,sizeof(D));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<n;k++){
                D[i][j]+=A[i][k]*B[k][j]%mod;
                D[i][j]%=mod;
            }
        }
    }
    cp(A,D,n);
}

int C[N][N];
void _pow(int A[N][N],LL b,int n){
    memset(C,0,sizeof(C));
    for(int i=0;i<n;i++){
        C[i][i]=1;
    }
    while(b){
        if(b&1){
            _mul(C,A,n);
        }
        _mul(A,A,n);
        b/=2;
    }
    cp(A,C,n);
}

void fco(int aa[N],int i){
    for(int j=top-1;j>=0;j--){
        aa[j]=i/ww[j];
        i%=ww[j];
    }
}

int A[N][N],B[N][N];
int aa[N];
void getA(int co){
    memset(A,0,sizeof(A));
    for(int i=0;i<co;i++){
        for(int j=0;j<26;j++)if(ve[j].size()){
            if(ve[j][0]==1){
                A[i][i]++;
            }
            else {
                fco(aa,i);

                for(int jj=ll[j];jj<=rr[j];jj++){
                    aa[jj]++;aa[jj]%=sta[jj];
                }

                int ii=0;
                for(int jj=0;jj<top;jj++){
                    ii+=aa[jj]*ww[jj];
                }
                A[ii][i]++;
            }
        }
    }
}

void getB(){
    memset(B,0,sizeof(B));
    for(int i=0;i<26;i++)if(ve[i].size()){
        if(ve[i][0]==1){
            B[0][0]++;
        }
        else {
            int ans=0;
            for(int j=ll[i];j<=rr[i];j++){
                ans+=ww[j];
            }
            B[ans][0]++;
        }
    }
}

int geta(int co){
    int ans=0;
    for(int i=0;i<co;i++){
        fco(aa,i);
        int fg=1;
        for(int j=0;j<26;j++)if(ve[j].size()&&ve[j][0]!=1){
            int flag=0;
            for(int jj=ll[j];jj<=rr[j];jj++){
                if(aa[jj]==0){
                    flag=1;break;
                }
            }
            fg=flag;
            if(!fg)break;
        }
        if(fg){
            ans+=A[i][0];ans%=mod;
        }
    }
    return ans;
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi
    LL n;int c;
    while(scanf("%I64d%d",&n,&c)!=EOF){
        for(int i=0;i<26;i++){
            ve[i].clear();
        }
        for(int i=0;i<c;i++){
            char ss[2];int a;
            scanf("%s%d",ss,&a);
            ve[ss[0]-'A'].pb(a);
        }
        if(n==0){
            printf("1\n");continue;
        }

        for(int i=0;i<26;i++){
            sort(ve[i].begin(),ve[i].end());
            ve[i].erase(unique(ve[i].begin(),ve[i].end()),ve[i].end());
            //printf("%d\n",ve[i].size());
        }

        int co=1;
        top=0;
        for(int i=0;i<26;i++)if(ve[i].size()&&ve[i][0]!=1){
            ll[i]=top;
            for(int j=0;j<ve[i].size();j++){
                sta[top]=ve[i][j];
                ww[top]=co;
                co*=ve[i][j];
                top++;
            }
            rr[i]=top-1;
        }

        getA(co);
        _pow(A,n-1,co);
        getB();
        _mul(A,B,co);
        printf("%d\n",geta(co));
    }
    return 0;
}

#include<cstdio>
#include<cmath>
#include<vector>
#include<queue>
#include<map>
#include<cstring>
#include<algorithm>
using namespace std;
#define LL long long
#define M 305
#define Mod 12345
const double eps=1e-9;
LL read() {
    LL x=0;
    LL f=1;
    char c=getchar();
    while(c<'0'||c>'9') {
        if(c=='-')
            f=-f;
        c=getchar();
    }
    while(c>='0'&&c<='9') {
        x=x*10+c-'0';
        c=getchar();
    }
    x*=f;
    return x;
}
LL maxn[30];
vector<LL>G[30];
struct matrix{
	LL s[M][M];
	void inti(){
		memset(s,0,sizeof(s));
		return ;
	}
	void One(){
		inti();
		for(int i=1;i<=123;i++)
			s[i][i]=1;
		return ;
	}
	matrix operator *(matrix b)const{
		matrix f;
		f.inti();
		for(int i=1;i<=123;i++)
			for(int j=1;j<=123;j++)
				for(int k=1;k<=123;k++)
					f.s[i][j]=(f.s[i][j]+s[i][k]*b.s[k][j]%Mod)%Mod;
		return f;
	}
}mat,ret;
struct node{
	LL val[30];
	bool operator <(node b)const{
		for(int i=1;i<=26;i++){
			if(val[i]==b.val[i])
				continue;
			return val[i]<b.val[i];
		}
		return 0;
	}
}st;
LL cnt;
map<node,LL>a;
void dfs(LL p,node now){
	if(p==27){
		a[now]=++cnt;
		return ;
	}
	if(!maxn[p])
		dfs(p+1,now);
	for(int i=0;i<maxn[p];i++){
		now.val[p]=i;
		dfs(p+1,now);
	}
}
LL ans;
void calc(LL p,node now){
	if(p==27){
		ans=(ans+ret.s[1][a[now]])%Mod;
		return ;
	}
	if(!maxn[p])
		calc(p+1,now);
	for(int i=0;i<maxn[p];i++){
		bool f=0;
		for(int j=0;j<G[p].size();j++)
			if(i%G[p][j]==0){
				f=1;
				break;
			}
		if(f){
			now.val[p]=i;
			calc(p+1,now);
		}
	}
}
LL n=read(),m=read();
bool vis[30];
int main(){
	if(n==0){
		puts("1");
		return 0;
	}
	if(m==0){
		puts("0");
		return 0;
	}
	for(int i=1;i<=m;i++){
		char A;
		LL x;
		scanf(" %c %lld",&A,&x);
		LL c=A-'A'+1;
		if(x==0){
			vis[c]=1;
		}
		if(!maxn[c])
			maxn[c]=x;
		else
			maxn[c]*=x;
		G[c].push_back(x);
	}
	for(int i=1;i<=26;i++)
		if(vis[i])
			maxn[i]=0;
	dfs(1,st);
	for(map<node,LL> ::iterator it=a.begin();it!=a.end();it++){
		node pt=it->first;
		LL s=it->second;
		for(int j=1;j<=26;j++){
			if(!maxn[j])
				continue;
			node tp=pt;
			tp.val[j]=(tp.val[j]+1)%maxn[j];
			mat.s[s][a[tp]]++;
		}
	}
	ret.One();
	n;
	while(n){
		if(n&1)
			ret=ret*mat;
		n>>=1;
		mat = mat * mat;
	}
	calc(1,st);
	printf("%lld",ans);
}

#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 20);
const int mod = (int)12345;
const int64_t inf = (int64_t)1e16 + 42;

template<class T>
struct matrix
{
	int n;
	vector<vector<T> > t;

	matrix(int _n, T val) {n = _n; t.assign(n, vector<T>(n, val)); }
	matrix(int _n) {n = _n; t.assign(n, vector<T>(n, 0)); }
    matrix() { n = 0; t.clear(); }

	matrix operator * (matrix b)
	{
		matrix c = matrix(n, 0);
		for(int i = 0; i < n; i++)
			for(int k = 0; k < n; k++)
				for(int j = 0; j < n; j++)
					c.t[i][j] = (c.t[i][j] + t[i][k] * b.t[k][j]) % mod;
		return c;
	}

	vector<T> operator * (vector<T> b)
	{
		vector<T> c = vector<T>(n, 0);
		for(int i = 0; i < n; i++)
			for(int j = 0; j < n; j++)
                c[i] = (c[i] + t[i][j] * b[j]) % mod;

		return c;
	}

	matrix<T> operator ^ (matrix<T> b)
	{
		matrix<T> c = matrix(n, inf);
		for(int i = 0; i < n; i++)
			for(int k = 0; k < n; k++)
				for(int j = 0; j < n; j++)
					c.t[i][j] = min(c.t[i][j], t[i][k] + b.t[k][j]);
		return c;
	}

	matrix<T> operator + (matrix<T> b)
	{
		matrix<T> c = matrix<T>(n);
		for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                c.t[i][j] =  (t[i][j] + b.t[i][j]) % mod;

		return c;
	}

	matrix<T> operator - (matrix<T> b)
	{
		matrix<T> c = matrix<T>(n);
		for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                c.t[i][j] = (t[i][j] - b.t[i][j] + mod) % mod;

		return c;
	}

	matrix operator & (matrix b)
	{
		matrix<T> c = matrix<T>(n, -inf);
		for(int i = 0; i < n; i++)
			for(int k = 0; k < n; k++)
				for(int j = 0; j < n; j++)
					c.t[i][j] = max(c.t[i][j], t[i][k] + b.t[k][j]);

		return c;
	}
};

template<class T>
matrix<T> pow_min(matrix<T> base, int64_t p)
{
	if(p == 1) return base;

	if(p % 2ll == 0ll)
	{
		matrix<T> d = pow_min(base, p / 2ll);
		return d ^ d;
	}

	return base ^ pow_min(base, p - 1);
}

template<class T>
matrix<T> pow(matrix<T> base, int64_t p)
{
	if(p == 1) return base;

	if(p % 2ll == 0ll)
	{
		matrix<T> d = pow(base, p / 2ll);
		return d * d;
	}

	return base * pow(base, p - 1);
}

template<class T>
void print(matrix<T> mat)
{
	for(int i = 0; i < mat.n; i++)
		for(int j = 0; j < mat.n; j++)
			if(mat.t[i][j] < inf) cout << mat.t[i][j] << " \n"[j == mat.n - 1];
			else cout << "inf" << " \n"[j == mat.n - 1];

	cout << endl;
}

int64_t n, c;
vector<int> li[1 << 8];
int prod[1 << 8];

void read()
{
    for(char let = 'A'; let <= 'Z'; let++) prod[let] = -1;

    cin >> n >> c;
    for(int i = 0; i < c; i++)
    {
        char let;
        cin >> let;
        int cnt;
        cin >> cnt;

        if(prod[let] == -1) prod[let] = 1;
        prod[let] *= cnt;
        li[let].push_back(cnt);
    }
}

int sz = 1;

void solve()
{
    vector<char> pos;
    for(int i = 'A'; i <= 'Z'; i++)
        if(prod[i] != -1) sz *= prod[i], pos.push_back(i);

    matrix<int64_t> base = matrix<int64_t>(sz);
    vector<int64_t> vec = vector<int64_t>(sz, 0);
    vec[0] = 1;

    for(int state = 0; state < sz; state++)
    {
        int pw = 1;
        for(char let: pos)
        {
            int cc = ((state / pw) % prod[let]), nc = (((state / pw) % prod[let]) + prod[let] - 1) % prod[let];
            base.t[state][state - cc * pw + nc * pw]++;
            pw *= prod[let];
        }
    }

    if(n != 0)
    {
        base = pow(base, n);
        vec = base * vec;
    }

    int64_t ans = 0;
    for(int state = 0; state < sz; state++)
    {
        int pw = 1, ok = 1;
        for(char let: pos)
        {
            int cc = ((state / pw) % prod[let]), cok = 0;
            for(int x: li[let]) if(cc % x == 0) cok = 1;
            ok &= cok;
            pw *= prod[let];
        }

        ans = (ans + ok * vec[state]) % mod;
    }

    cout << ans << endl;
}

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

	read();
	solve();
	return 0;
}

//#define MY_DEBUG

#include <set>
#include <string>
#include <vector>
#include <map>
#include <queue>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cmath>
#pragma comment(linker, "/STACK:64000000")

using namespace std;

#ifdef MY_DEBUG
#include <fstream>
ifstream cin("input.txt");
ofstream cout("output.txt");
//ifstream cin("game.in");
//ofstream cout("game.out");
#else
#include <iostream>
#endif

const long double eps =  1e-6;
const long long inf = 1000000007;
const long long linf = (long long)1e18;
const long double pi = acos(-1.0);
const int prime = 53;

inline void finclude(){
#ifdef MY_DEBUG
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
#endif
    srand(time(NULL));
}

long long mx[123][123] = {}, ans[123][123] = {}, he[123][123] = {}, mod = 12345;
int c[256] = {}, g[256] = {};

void build(vector<char> a, vector<int> b, int m){
    int d[256] = {}, x;
    for(int i = 0; i < m; ++i){
        x = i;
        for(int j = 'A'; j <= 'Z'; ++j){
            if (c[j] != 0){
                d[j] = x % c[j];
                x /= c[j];
            }
        }
        for(int j = 'A'; j <= 'Z'; ++j){
            if (c[j] != 0){
                x = i;
                x -= d[j] * g[j];
                d[j] = (d[j] + 1) % c[j];
                x += d[j] * g[j];
                ++mx[x][i];
            }
        }
    }
}

int main(){
    long long n, m = 1, K;
    cin >> n >> K;
    vector<char> a(K);
    vector<int> b(K);
    for(int i = 0; i < K; ++i){
        cin >> a[i] >> b[i];
        if (c[a[i]] == 0)
            c[a[i]] = b[i];
        else
            c[a[i]] *= b[i];
        m *= b[i];
    }
    long long x = 1;
    for(int i = 'A'; i <= 'Z'; ++i){
        if (c[i] != 0){
            g[i] = x;
            x *= c[i];
        }
    }
    build(a, b, m);
    for(int i = 0; i < m; ++i)
        ans[i][i] = 1;
    while(n != 0){
        if (n % 2 == 1){
            --n;
            for(int i = 0; i < m; ++i){
                for(int j = 0; j < m; ++j){
                    he[i][j] = 0;
                    for(int k = 0; k < m; ++k)
                        he[i][j] += ans[i][k] * mx[k][j];
                }
            }
            for(int i = 0; i < m; ++i)
                for(int j = 0; j < m; ++j)
                    ans[i][j] = he[i][j] % mod;
        }
        n /= 2;
        for(int i = 0; i < m; ++i){
            for(int j = 0; j < m; ++j){
                he[i][j] = 0;
                for(int k = 0; k < m; ++k)
                    he[i][j] += mx[i][k] * mx[k][j];
            }
        }
        for(int i = 0; i < m; ++i)
            for(int j = 0; j < m; ++j)
                mx[i][j] = he[i][j] % mod;
    }
    long long an = 0;
    for(int i = 0; i < m; ++i){
        int x = i;
        int d[256] = {};
        bool find = false;
        for(int j = 'A'; j <= 'Z'; ++j){
            if (c[j] != 0){
                d[j] = x % c[j];
                x /= c[j];
            }
        }
        for(int j = 'A'; j <= 'Z'; ++j)
            for(int k = 0; k < K; ++k)
                if (a[k] == j && d[j] % b[k] == 0)
                    d[j] = 0;
        for(int j = 'A'; j <= 'Z'; ++j)
            if (d[j] != 0)
                find = true;
        if (find)
            continue;
        an = (an + ans[i][0]) % mod;
    }
    cout << an << '\n';
    return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define ZERO (1e-10)
#define INF int(1e9+1)
#define CL(A,I) (memset(A,I,sizeof(A)))
#define DEB printf("DEB!\n");
#define D(X) cout<<"  "<<#X": "<<X<<endl;
#define EQ(A,B) (A+ZERO>B&&A-ZERO<B)
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
#define IN(n) int n;scanf("%d",&n);
#define FOR(i, m, n) for (int i(m); i < n; i++)
#define F(n) FOR(i,0,n)
#define FF(n) FOR(j,0,n)
#define FT(m, n) FOR(k, m, n)
#define aa first
#define bb second
void ga(int N,int *A){F(N)scanf("%d",A+i);}
#define MM (1001)
void mul(int A[MM][MM],int B[MM][MM],int R[MM][MM],int W,int M){
    F(W)FF(W)R[i][j]=0;
    F(W)FF(W){
        ll D=M*1ll*M,S=0;;
        FT(0,W)if((S+=A[i][k]*1ll*B[k][j])>=D)S-=D;
        R[i][j]=S%M;
    }
}
void pw(int M[MM][MM],int R[MM][MM],int W,ll k,int MD){
    static int E[MM][MM],H[MM][MM];
    F(W)FF(W)R[i][j]=E[i][j]=i==j;
    while(k){
        if(k&1)mul(E,M,R,W,MD),memcpy(E,R,sizeof(E));
        mul(M,M,H,W,MD);
        memcpy(M,H,sizeof(H));
        k>>=1;
    }
}
int lcm(int a,int b){return  a/__gcd(a,b)*b;}
vi o[26];
char c;
ll N;
int Q,a,C;
void nrm(vi&o){
    F((int)o.size()){
        bool x=0;
        FF((int)o.size())if(i^j&&!(o[i]%o[j]))x=1;
        if(x)o[i]=o.back(),o.pop_back(),--i;
    }
}
int mp(vi&o){return accumulate(o.begin(),o.end(),1,lcm);}
#define MOD 12345
int M[MM][MM],R[MM][MM],L[26];
bool dv(int I,vi&o){for(auto&h:o)if(!(I%h))return 1;return o.empty();}
map<vi,int> T;
void rec(int u,vi r,bool x,int l){
    if(u==26){
        if(!T.count(r))T[r]=C++;
        int I=T[r];
        if(x)M[I][l]=1;
        F(26)if(!o[i].empty()){
            ++r[i]%=L[i];
            if(!T.count(r))T[r]=C++;
            ++M[I][T[r]];
            r[i]+=L[i]-1,r[i]%=L[i];
        }
        return;//TODO
    }
    r.PB(-1);
    F(L[u])r.back()=i,rec(u+1,r,x&dv(i,o[u]),l);
}
int go(ll N){
    CL(M,0);
    int l=1;
    F(26)l*=mp(o[i]);
    vi r;
    rec(0,r,1,l);
    ++l;
//    F(l)FF(l)printf("%d%c",M[i][j],j+1==l?10:32);
    pw(M,R,l,N+1,MOD);
    return R[0][l-1];
}
int main(void){
    scanf("%lld%d",&N,&Q);
    F(Q)scanf(" %c%d",&c,&a),o[c-65].PB(a);
    F(26)nrm(o[i]),L[i]=mp(o[i]);
//    D(go(N))//TODO ERASE
//    D(go(N-1))
//    printf("%d\n",(go(N)-go(N-1)+MOD)%MOD);
    printf("%d\n",go(N));
    return 0;
}//This shall not work.. actually no idea why it passes samples :'(

#include <bits/stdc++.h>

using namespace std;

#define dbgs(x) cerr << (#x) << " --> " << (x) << ' '
#define dbg(x) cerr << (#x) << " --> " << (x) << endl

#define foreach(i,x) for(type(x)i=x.begin();i!=x.end();i++)
#define FOR(ii,aa,bb) for(int ii=aa;ii<=bb;ii++)
#define ROF(ii,aa,bb) for(int ii=aa;ii>=bb;ii--)

#define type(x) __typeof(x.begin())

#define orta (bas + son >> 1)
#define sag (k + k + 1)
#define sol (k + k)

#define pb push_back
#define mp make_pair

#define nd second
#define st first

#define endl '\n'

typedef pair < int ,int > pii;

typedef long long ll;

const long long linf = 1e18+5;
const int mod = 12345;
const int logN = 17;
const int inf = 1e9;
const int N = 1100;

int x, n, m, w[N], pre[N], t[N];
vector< int > v[N];
char c;
ll k;

class	matrix {
	public:
		vector< vector< int > >	a;
		matrix(int k) {
			a.resize(124);
			FOR(i, 0, 123)
				a[i].resize(124, 0);
			FOR(i, 0, 123)
				a[i][i] = k;
		}
		vector< int >& operator[](int x) { return a[x]; }
		matrix operator*(matrix b) {
			matrix ans(0);
			FOR(k, 0, 123)
				FOR(i, 0, 123)
					FOR(j, 0, 123)
						ans[i][j] = (ans[i][j] + a[i][k] * b[k][j]) % mod;
			return ans;
		}
};

int main() {
	scanf("%lld %d", &k, &n);
	FOR(i, 0, 25) w[i] = 1;
	FOR(i, 1, n) {
		scanf(" %c %d", &c, &x); c -= 'A';
		v[c].pb(x);
		w[c] = w[c] * x / __gcd(x, w[c]);
		t[c] = 1;
	}
	int cnt = 0, all = 1; matrix A(0), B(1);
	FOR(i, 0, 25) {
		pre[i] = i ? pre[i-1] * w[i] : w[i];
		all *= w[i];
	}
	FOR(i,0,all-1)
		FOR(j,0,all-1) {
			int flag = false, c = 0, c2 = 0;
			FOR(k, 0, 25) {
				if(!t[k]) continue;
				int md1 = (i / (k ? pre[k-1] : 1)) % w[k];
				int md2 = (j / (k ? pre[k-1] : 1)) % w[k];
				if((md1 + 1) % w[k] == md2) {
					if(w[k] > 1)
						c++;
					c2++;
				}
				else if(md1 != md2)
					flag = true;
			}
			if(flag) continue;
			if(c <= 1)
				A[i][j] = c ? 1 : c2;
		}
	int flag = false;
	while(k) {
		if(k & 1) {
			if(!flag)
				B = A;
			else
				B = B * A;
			flag = true;
		}
		A = A * A;
		k >>= 1;
	}
	int ans = 0;
	FOR(i, 0, all-1) {
		bool flag = 0;
		FOR(k, 0, 25) {
			if(!t[k]) continue;
			int t = 0, md1 = (i / (k ? pre[k-1] : 1)) % w[k];
			foreach(it, v[k])
				if(md1 % *it == 0)
					t = 1;
			flag |= !t;
		}
		if(!flag)
			ans = (ans + B[0][i]) % mod;
	}
	cout << ans << endl;
	return 0;
}

#include <cstdio>
#include <vector>
#define maxn 1010
const int mod = 12345;
inline int min(int a, int b) {return a < b ? a : b;}
inline int max(int a, int b) {return a > b ? a : b;}
inline void up(int &a, int b) {if ((a += b) >= mod) a -= mod;}
inline long long pw(long long base, long long p) {
	base %= mod;
	long long res = 1;
	for (; p; p >>= 1, base = base * base % mod) if (p & 1) res = res * base % mod;
	return res;
}

int __sz = 1;
struct matrix {
	#define __M 150
	#define M __sz
	int s[__M][__M];
	inline matrix() {
		__builtin_memset(s, 0, sizeof s);
	}
	inline friend matrix operator * (const matrix &lhs, const matrix &rhs) {
		matrix res;
		for (register int i = 0; i < M; i++) {
			for (register int j = 0; j < M; j++) {
				long long tmp = 0;
				for (register int k = 0; k < M; k++) tmp += static_cast<long long> (lhs.s[i][k]) * rhs.s[k][j];
				res.s[i][j] = tmp % mod;
			}
		}
		return res;
	}
	#undef __M
	#undef M
} BASE, RES;

long long n;
int m;
int mp[300], ret[300], __name, prod[300];
int base[300];
std::vector<int> v[300];
inline int get(int x, int i) {return x / base[i - 1] % prod[i];}
inline bool check(int x) {
	for (int i = 1; i <= __name; i++) {
		bool find = false;
		int now = get(x, i);
		for (std::vector<int>::iterator it = v[i].begin(); it != v[i].end(); it++) if (now % *it == 0) {
			find = true;
			break;
		}
		if (!find) return false;
	}
	return true;
}

int main() {
//	freopen("too.in", "r", stdin);
//	freopen("too.out", "w", stdout);
	scanf("%lld%d", &n, &m);
	for (int i = 1, x, ch; i <= m; i++) {
		char __ch;
		scanf("%1s%d", &__ch, &x); ch = static_cast<int>(__ch);
		if (!mp[ch]) mp[ch] = ++__name, ret[__name] = ch, prod[__name] = 1;
		prod[mp[ch]] *= x;
		v[mp[ch]].push_back(x);
		__sz *= x;
	}
	base[0] = 1; for (int i = 1; i <= __name; i++) base[i] = base[i - 1] * prod[i];
	for (int i = 0; i < __sz; i++) {
		for (int j = 1; j <= __name; j++) {
			int now = get(i, j), nxt = (now + 1) % prod[j];
			up(BASE.s[i][i + (nxt - now) * base[j - 1]], 1);
		}
	}
	RES.s[0][0] = 1;
	for (; n; n >>= 1, BASE = BASE * BASE) if (n & 1) RES = RES * BASE;
	int ans = 0;
	for (int i = 0; i < __sz; i++) if (check(i)) up(ans, RES.s[0][i]);
	printf("%d\n", ans);
	return 0;
}

#include <array>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
using namespace std;
namespace fio {
streambuf* in = cin.rdbuf();
char bb[1000000], *s = bb, *t = bb;
#define gc() \
  (s == t && (t = (s = bb) + in->sgetn(bb, 1000000), s == t) ? EOF : *s++)
inline long long read() {
  long long x = 0;
  char ch = gc();
  while (ch < 48) ch = gc();
  while (ch >= 48) x = x * 10 + ch - 48, ch = gc();
  return x;
}
}  // namespace fio
using fio::read;
long long n;
int m, llm;
int lim[26];
vector<int> road[26];
map<array<int, 26>, int> huaji;
array<int, 26> pm;
class mat {
 public:
  int val[125][125];
  int* operator[](int x) { return val[x]; }
  mat operator*(mat _) {
    mat ans;
    for (int i = 1; i <= llm; i++)
      for (int u = 1; u <= llm; u++) {
        ans[i][u] = 0;
        for (int j = 1; j <= llm; j++)
          ans[i][u] = (ans[i][u] + val[i][j] * _[j][u]) % 12345;
      }
    return ans;
  }
};
mat ksm(mat x, long long y) {
  mat ans = x;
  y--;
  for (; y; y >>= 1, x = x * x)
    if (y & 1) ans = ans * x;
  return ans;
}
mat base;
int ans;
int main() {
  n = read(), m = read();
  if (!n) return cout << 1, 0;
  if (!m) return cout << 0, 0;
  for (int i = 1, x, y; i <= m; i++)
    x = read() + '0' - 'A', road[x].emplace_back(y = read()),
    lim[x] = max(lim[x], 1) * road[x].back();
  while (pm[25] < max(lim[25], 1)) {
    huaji[pm] = ++llm, pm[0]++;
    for (int i = 0; i < 25; i++)
      if (lim[i])
        pm[i + 1] += pm[i] / lim[i], pm[i] %= lim[i];
      else
        pm[i + 1] += pm[i], pm[i] = 0;
  }
  for (pair<array<int, 26>, int> it : huaji)
    for (int i = 0; i < 26; i++)
      if (lim[i])
        it.first[i] = (it.first[i] + 1) % lim[i],
        base[it.second][huaji[it.first]]++,
        it.first[i] = (it.first[i] - 1 + lim[i]) % lim[i];
  base = ksm(base, n);
  for (pair<array<int, 26>, int> it : huaji) {
    bool flag = 1;
    for (int i = 0, fx = 0; flag && i < 26; i++, flag &= fx, fx = 0)
      if (!lim[i])
        fx = 1;
      else
        for (int p : road[i]) fx |= !(it.first[i] % p);
    flag ? ans = (ans + base[1][it.second]) % 12345 : ans;
  }
  cout << ans << endl;
}

#include <bits/stdc++.h>
#ifdef _MSC_VER
#define __builtin_popcount (int)__popcnt
#define __builtin_popcountll (int)__popcnt64
#define __builtin_clz (int)__lzcnt
#define $ system("pause")
#define gp_hash_table unordered_map
#else
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define $
//#define USACO
//#define IOI_style
#endif

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double ld;
typedef complex<double> point;

#define MOD 12345
#define MAXN 123
#define LG 20
#define inf int(1e9 + 100)

#define rep(i, j, k) for (int i = j; i < k; i++)
#define for_all(x) x.begin(), x.end()
#define lid id << 1
#define rid id << 1 | 1
#define lch l, mid, lid
#define rch mid, r, rid
#define pb push_back
#define X first
#define Y second
#define re real()
#define im imag()

template <typename S, typename T>
inline ostream &operator<<(ostream &out, const pair<S, T> &p)
{
	return out << "( " << p.X << " , " << p.Y << " )";
}
template <typename S>
inline ostream &operator<<(ostream &out, const vector<S> &p)
{
	for (auto &e : p) out << e; return out;
}
template <typename T, typename S>
inline T smin(T &a, const S &b) { return a > b ? a = b : a; }
template <typename T, typename S>
inline T smax(T &a, const S &b) { return a < b ? a = b : a; }
inline double dot(const point l, const point r) { return l.re * r.re + l.im * r.im; }
inline double cross(const point l, const point r) { return l.re * r.im - l.im * r.re; }
ll po(ll v, ll u) { return u ? (po(v * v % MOD, u >> 1) * (u & 1 ? v : 1) % MOD) : 1; }
template<class T> inline void add(T &l, const T &r) { l = (l + r) % MOD; }
ll gcd(ll v, ll u) { return u ? gcd(u, v % u) : v; }

ll n;
int c;
vector<int> vec, o[30];

struct Mat {
	int n, m;
	int arr[MAXN][MAXN];
	Mat(int n, int m, int z = 0) : n(n), m(m) {
		memset(arr, 0, sizeof(arr));
		rep(i, 0, min(n, m))
			arr[i][i] = z;
	}
};

inline ostream &operator<<(ostream &out, Mat &p)
{
	rep(i, 0, p.n) {
		rep(j, 0, p.m)
			cout << p.arr[i][j] << ' ';
		cout << endl;
	}
	return out;
}

inline Mat operator*(Mat l, Mat r) {
	Mat res(l.n, r.m);
	rep(i, 0, res.n) rep(j, 0, res.m) rep(k, 0, l.m)
		add(res.arr[i][j], l.arr[i][k] * r.arr[k][j]);
	return res;
}

Mat operator^ (const Mat & v, ll u)
{
	Mat res(v.n, v.m, 1);
	for (int i = 62; ~i; i--) {
		res = res * res;
		if (u & (1ll << i)) res = res * v;
	}
	return res;
}

vector<int> state, f[MAXN];
map<vector<int>, int> rf;
int NOW, sz[MAXN];
void build(int g = 0) {
	if (g == c) {
		f[NOW] = state;
		rf[state] = NOW++;
		return;
	}
	rep(i, 0, sz[vec[g]]) {
		state[g] = i;
		build(g + 1);
	}
	return;
}

#ifndef IOI_style
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
#ifdef USACO
	freopen("gathering.in", "r", stdin);
	freopen("gathering.out", "w", stdout);
#endif
	cin >> n >> c;
	rep(i, 0, c) {
		char v; int m;
		cin >> v >> m;
		v -= 'A';
		vec.pb(v);
		o[v].pb(m);
	}
	sort(for_all(vec));
	vec.resize(unique(for_all(vec)) - vec.begin());
	for (auto e : vec) {
		sort(for_all(o[e]));
		o[e].resize(unique(for_all(o[e])) - o[e].begin());
		sz[e] = 1;
		for (auto z : o[e]) sz[e] *= z;
	}
	state.resize(vec.size());
	c = vec.size(); build();
	Mat M(NOW, NOW);
	rep(i, 0, NOW) {
		auto v = f[i];
		rep(j, 0, c) {
			v[j] = (v[j] + 1) % sz[vec[j]];
			M.arr[rf[v]][i]++;
			v[j] = (v[j] - 1 + sz[vec[j]]) % sz[vec[j]];
		}
	}
	M = M ^ n;
	int answer = 0;
	rep(i, 0, NOW) {
		auto v = f[i];
		bool bad = false;
		rep(j, 0, c) {
			bool flag = false;
			for (auto z : o[vec[j]])
				if (v[j] % z == 0) flag = true;
			if (!flag) bad = true;
		}
		if (bad) continue;
		add(answer, M.arr[i][0]);
	}
	cout << answer << endl;
	$;
	return 0;
}
#endif

#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cctype>
#include <iomanip>
#include <bitset>
#include <list>
#include <deque>
#include <utility>
#include <functional>
#include <cassert>
#include <complex>

using namespace std;

#define all(a)              (a).begin(), (a).end()
#define ms(a,b)             memset(a, b, sizeof(a))
#define mp                  make_pair
#define pb                  push_back
#define fore(it,a)          for (auto it = (a).begin(), it##_ = (a).end(); it != it##_; ++it)
#define f0r(i, a)           for (int i = 0, i##_ = (a); i < i##_; ++i)
#define debug(args...)      do {cerr << #args << ": "; dbg,args; cerr << endl;} while(0)
#define read(type, args...) type args; rdr,args;
#define fi                  first
#define se                  second
#define bit_no              __builtin_popcount
#define left(a)             (2*(a))
#define right(a)            (2*(a)+1)
#define mid(left, right)    (((left)+(right))/2+1)
#define PI                  acos(-1)

typedef long long               ll;
typedef long double             ld;
typedef unsigned long long      ull;
typedef vector<int>             vi;
typedef vector<vi>              vvi;
typedef pair<int, int>          ii;
typedef tuple<int, int, int>    iii;
typedef vector<ii>              vii;
typedef vector<iii>             viii;

template<typename T>
using min_pq = priority_queue<T, vector<T>, greater<T>>;

const int inf = 2e8+5;
const ll l_inf = 9e18+5;
const int mod_v = 12345;
const int max_n = 1e5+5;

template<typename T>
T gcd(T a, T b)
{
    while (b) {
        T temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}

template<typename T>
tuple<T, T, T> egcd(T a, T b)
{
    T x1 = 1, x2 = 0, y1 = 0, y2 = 1;
    while (b) {
        T q = a / b, r = a % b;
        T new_x = x1 - q*x2, new_y = y1 - q*y2;
        x1 = x2, y1 = y2, x2 = new_x, y2 = new_y;
        a = b, b = r;
    }
    return make_tuple(a, x1, y1);
}

inline ll lcm(ll a, ll b)
{
    return a*b/gcd(a, b);
}

template<typename T>
inline T mod(T a, T b = mod_v)
{
    return (a % b + b) % b;
}

template<typename T>
inline T mod_inv(T a, T b = mod_v)
{
    return mod(get<1>(egcd(a, b)), b);
}

template<typename T>
inline T sum(T a, T b, T m = mod_v)
{
    return mod(mod(a, m) + mod(b, m), m);
}

template<typename T>
inline T difference(T a, T b, T m = mod_v)
{
    return mod(mod(a, m) - mod(b, m), m);
}

inline ll product(ll a, ll b, ll m = mod_v)
{
    return mod(mod(a, m) *  mod(b, m), m);
}

inline ll quotient(ll a, ll b, ll m = mod_v)
{
    return mod(mod(a, m) * mod_inv(b, m), m);
}

template<typename T,typename T2>
ostream& operator<< (ostream &s, const pair<T,T2> &p) {return s << p.fi << ' ' << p.se << ' ';}

template<typename T,typename T2>
istream& operator>> (istream &s, pair<T,T2> &p) {return s >> p.fi >> p.se;}

template<typename T>
ostream& operator<< (ostream &s, const vector<T> &v)  {for (auto it: v) s << it << ' '; return s;}

template<typename T>
istream& operator>> (istream &s, vector<T> &v) {fore (it, v) s >> *it; return s;}

template<typename T>
void read_range(T beg, T end)
{
    while (beg != end)
        cin >> *beg++;
}

template<typename T>
void print_range(T beg, T end)
{
    while (beg != end)
        cout << *beg++ << ' ';
}

struct reader
{
    template<typename T>
    reader& operator, (T &v)
    {
        cin >> v;
        return *this;
    }
} rdr;

struct debugger
{
    template<typename T>
    debugger& operator, (const T &v)
    {
        cerr << v << ", ";
        return *this;
    }
} dbg;

/***************************************************************
----------------------------------------------------------------
----------------------------------------------------------------
***************************************************************/

int ar[130][130];
int res[130][130];
int temp[130][130];
int mult[26];
int hash_mult[27];
vi mult2[26];

void prod(int a[][130], const int b[][130])
{
    f0r (i, 130)
        f0r (j, 130) {
            temp[i][j] = 0;
            f0r (k, 130)
                temp[i][j] = (temp[i][j] + a[i][k] * b[k][j]) % mod_v;
        }
    memcpy(a, temp, sizeof(temp));
}

void power(ll p)
{
    f0r (i, 130)
        res[i][i] = 1;
    while (p) {
        if (p & 1)
            prod(res, ar);
        prod(ar, ar);
        p >>= 1;
    }
}

void init_hash()
{
    f0r (i, 27) {
        if (i == 0) hash_mult[i] = 1;
        else hash_mult[i] = (hash_mult[i-1] * max(1, mult[i-1]));
    }
}

bool correct(int i) {
    f0r (j, 26)
        if (mult[j]) {
            int cur_cnt = (i / hash_mult[j]) % mult[j];
            bool ok = false;
            for (int m : mult2[j])
                if (cur_cnt % m == 0) ok = true;
            if (!ok) return false;
        }

    return true;
}

void init_ar()
{
    f0r (i, 130) {
        f0r (j, 26)
            if (mult[j]) {
                int cur_cnt = (i / hash_mult[j]) % mult[j];
                int new_cnt = (cur_cnt + 1) % mult[j];
                int new_s_no = i + (new_cnt - cur_cnt) * hash_mult[j];

                ar[i][new_s_no]++;
            }
    }
}

int main()
{
    ios_base::sync_with_stdio(false);

    read(ll, n);
    read(int, c);

    f0r (i, c) {
        read(char, ch);
        read(int, m);
        if (mult[ch - 'A'] == 0)
            mult[ch - 'A'] = m;
        else
            mult[ch - 'A'] = lcm(mult[ch - 'A'], m);
        mult2[ch - 'A'].pb(m);
    }

    init_hash();
    init_ar();

    power(n);

    int r = 0;
    f0r (i, hash_mult[26])
        if (correct(i))
            r = (r + res[0][i]) % mod_v;

    cout << r;

    return 0;
}

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<set>
#include<vector>
#define mod 12345
using namespace std;
long long a;
long long b,c,d,e,f,g[1005],h,i,j,k;
char w[10];
long long Q[1005][2],ok;
vector<long long>Z[27];
struct node
{
        long long x[155][155];

};
struct node F,G,H,root;
struct node CC;
node operator * (const node &x,const node &y)
{
        //memset(CC.x,0,sizeof(CC.x));
        for(int iii=1;iii<=d;iii++)
            for(int jjj=1;jjj<=d;jjj++)
            {
                CC.x[iii][jjj]=0;
                for(int kkkkk=1;kkkkk<=d;kkkkk++)
                {
                    CC.x[iii][jjj]+=x.x[iii][kkkkk]*y.x[kkkkk][jjj];
                    CC.x[iii][jjj]%=mod;
                }
            }
        return CC;
}
struct node1
{
        long long x[1005],num;
        friend bool operator < (const node1 &x,const node1 &y)
        {
                 long long iii;
                 for(iii=1;iii<=b;iii++)
                 {
                    if(x.x[iii]<y.x[iii]) return true;
                    if(x.x[iii]>y.x[iii]) return false;
                 }
                 return false;
        }
};
struct node1 E[1005];
struct node1 ch;
set<node1>GG;
set<node1>::iterator in,in1;
long long an;

void soso(long long x)
{
        long long ii,jj,kk;
        node1 ch1;
        if(x>b)
        {
                for(ii=1;ii<=b;ii++) ch1.x[ii]=g[ii];
                ch1.num=++d;
                E[d]=ch1;
                GG.insert(ch1);
                return ;
        }
        for(ii=0;ii<Q[x][1];ii++)
        {
                g[x]=ii;
                soso(x+1);
        }
}

void Mi(long long x)
{
        if(x==1)
        {
                F=root;
                return ;
        }
        Mi(x>>1);
        G=F*F;
        if(x&1) G=G*root;
        F=G;
}

bool Eq(node1 x,node1 y)
{
        long long ii;
        for(ii=1;ii<=b;ii++)
        if(x.x[ii]!=y.x[ii])
            return false;
        return true;
}

int main()
{
        scanf("%I64d%I64d",&a,&b);
        if(a==0 && b==0)
        {
                printf("1\n");
                return 0;
        }
        if(b==0)
        {
                printf("0\n");
                return 0;
        }
        if(a==0)
        {
                printf("1\n");
                return 0;
        }
        for(i=1;i<=b;i++)
        {
                scanf("%s%I64d",w,&Q[i][1]);
                Q[i][0]=w[0]-'A'+1;
                Z[Q[i][0]].push_back(i);
        }
        soso(1);
        for(i=1;i<=d;i++)
        {
                for(j=1;j<=26;j++)
                {
                        ok=0;
                        ch=E[i];
                        for(k=1;k<=b;k++)
                        if(Q[k][0]==j)
                        {
                                ok=1;
                                ch.x[k]+=Q[k][1];
                                ch.x[k]--;
                                ch.x[k]%=Q[k][1];
                        }
                        if(ok)
                        {
                                in=GG.lower_bound(ch);
                                if(Eq((*in),ch))
                                {
                                    e=(*in).num;
                                    root.x[e][i]++;
                                }
                        }
                }
        }
        Mi(a);
        /*for(i=1;i<=d;i++,printf("\n"))
            for(j=1;j<=d;j++)
                printf("%d ",root.x[i][j]);*/
        for(i=1;i<=d;i++)
        {
                /*for(j=1;j<=3;j++)
                {
                        printf("%d ",E[i].x[j]);
                }
                printf("\n");*/
                for(j=1;j<=26;j++)
                {
                        ok=0;
                        if(Z[j].size()==0) continue;
                        for(k=0;k<Z[j].size();k++)
                        if(E[i].x[Z[j][k]]==0)
                        {ok=1;break;}
                        if(ok==0) break;
                }
                if(j==27) an+=F.x[1][i];
                an%=mod;
        }
        printf("%I64d\n",an);
        return 0;
}

//107D Hewr
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define fo(i,a,b) for (int i = a; i <= b; ++i)
#define fd(i,a,b) for (int i = a; i >= b; --i)
#define fe(i,x) for (int i = g[x], y = E[i].y; i; i = E[i].l, y = E[i].y)
#define forall(i, x) for (typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)
#define pb push_back
#define SIZE(x) ((int) (x).size())
#define MP make_pair
#define fi first
#define se second
#define UNIQUE(x) x.resize(unique(x.begin(), x.end()) - x.begin())
#define clr(a,x) memset(&a, x, sizeof(a))
#define move(a,b) memcpy(&b, &a, sizeof(a))
#define Plus(a,b) (((LL) (a) + (b)) % mo)
#define Minus(a,b) ((((LL) (a) - (b) ) % mo + mo) % mo)
#define Mul(a,b) ((LL) (a) * (b) % mo)
#define updmin(a,b) (a = min(a, b))
#define updmax(a,b) (a = max(a, b))
#define sqr(x) ((x) * (x))

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef vector<int> VI;

const int oo = ~0u >> 2, mo = 12345;
const int mn = 26, mm = 20, ms = 200;

struct REC{
    int h, v;
    REC(){}
    REC(int _h, int _v){ h = _h, v = _v; }
};
vector<REC> rec;

struct MAT{ int a[ms]; } e, f;

int s[ms][ms], co[mm];
bool one[mn];
VI g[mn];
int m, l, num_one;
LL n;

MAT times(MAT a, MAT b){
    MAT ret; clr(ret, 0);
    fo (i, 0, l) fo (j, 0, l)
        ret.a[s[i][j]] = ((LL) a.a[i] * b.a[j] + ret.a[s[i][j]]) % mo;
    return ret;
}

MAT calc(LL n){
    if (n == 1) return e;
    MAT ret;
    if (n & 1){
        ret = calc(n - 1);
        ret = times(ret, e);
    } else {
        ret = calc(n / 2);
        ret = times(ret, ret);
    }
    return ret;
}

int main(){
    cin >> n >> m;
    if (!n){
        printf("1\n");
        return 0;
    }
    fo (i, 1, m){
        char ch; int t;
        do { cin >> ch; } while (ch < 'A' || ch > 'Z');
        cin >> t;
        int h = ch - 'A';
        if (t == 1) num_one += !one[h], one[h] = 1;
        else g[h].pb(t);
    }
    l = 1;
    fo (i, 0, mn - 1) if (!one[i]) fo (j, 0, SIZE(g[i]) - 1){
        rec.pb(*(new REC(i, g[i][j])));
        l *= g[i][j];
    }
    --l;
    fo (X, 0, l) fo (Y, 0, l){
        int sum[mm], x = X, y = Y;
        fo (i, 0, SIZE(rec) - 1)
            sum[i] = (x + y) % rec[i].v, x /= rec[i].v, y /= rec[i].v;
        s[X][Y] = 0;
        fd (i, SIZE(rec) - 1, 0) s[X][Y] = s[X][Y] * rec[i].v + sum[i];
    }
    co[0] = 1; fo (i, 1, SIZE(rec)) co[i] = co[i - 1] * rec[i - 1].v;
    clr(e, 0), e.a[0] = num_one;
    fo (i, 0, SIZE(rec) - 1){
        int t = 0;
        fo (j, 0, SIZE(rec) - 1) if (rec[i].h == rec[j].h) t += co[j];
        e.a[t] = 1;
    }
    f = calc(n);
    int Ans = 0;
    fo (i, 0, l) if (f.a[i]){
        bool v[mn];
        int t = i;
        clr(v, 0);
        fo (j, 0, SIZE(rec) - 1){
            if (!(t % rec[j].v)) v[rec[j].h] = 1;
            t /= rec[j].v;
        }
        bool flag = 1;
        fo (j, 0, SIZE(rec) - 1) if (!v[rec[j].h]){ flag = 0; break; }
        if (flag)
            Ans = (Ans + f.a[i]) % mo;
    }
    cout << Ans << endl;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int M = 12345;

int add(int a, int b) {
  a += b;
  if (a >= M) {
    return a - M;
  }
  if (a < 0) {
    return a + M;
  }
  return a;
}

int mul(int a, int b) {
  return a * (ll) b % M;
}

ll n;
int q;
vector<int> g[26];
int p[26];
vector<vector<int>> good;
vector<int> prods;
int sz;
int pall = 1;
int go[123][123];

int get(vector<int> a) {
  int sol = 0;
  for (int i = 0; i < sz; i++) {
    sol = sol * prods[i] + a[i];
  }
  return sol;
}

vector<int> get(int x) {
  vector<int> sol;
  for (int i = sz - 1; i >= 0; i--) {
    sol.push_back(x % prods[i]);
    x /= prods[i];
  }
  reverse(sol.begin(), sol.end());
  return sol;
}

void print(vector<int> a) {
  cout << " : ";
  for (auto &x : a) {
    cout << x << " ";
  }
  cout << "\n";
}

vector<int> operator * (vector<int> a, vector<int> b) {
  vector<int> c(pall, 0);
  for (int i = 0; i < pall; i++) {
    for (int j = 0; j < pall; j++) {
      int k = go[i][j];
      c[k] = add(c[k], mul(a[i], b[j]));
    }
  }
  return c;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> q;
  if (q == 0) {
    cout << (n == 0) << "\n";
    return 0;
  }
  while (q--) {
    string s;
    int x;
    cin >> s >> x;
    int i = s[0] - 'A';
    if (p[i] == 0) {
      p[i] = 1;
    }
    g[i].push_back(x);
    p[i] *= x;
  }
  for (int i = 0; i < 26; i++) {
    if (p[i]) {
      good.push_back(g[i]);
      prods.push_back(p[i]);
      sz++;
    }
  }
  pall = 1;
  for (auto &it : prods) {
    pall *= it;
  }
  for (int i = 0; i < pall; i++) {
    for (int j = 0; j < pall; j++) {
      vector<int> a = get(i), b = get(j);
      vector<int> c(sz);
      for (int k = 0; k < sz; k++) {
        c[k] = (a[k] + b[k]) % prods[k];
      }
      go[i][j] = get(c);
    }
  }
  vector<int> zero(sz, 0);
  vector<int> sol(pall, 0), cur(pall, 0);
  sol[0] = 1;
  for (int i = 0; i < sz; i++) {
    vector<int> alpha = zero;
    alpha[i] = 1 % prods[i];
    cur[get(alpha)] += 1;
  }
  for (int p = 0; (1LL << p) <= n; p++) {
    if (n & (1LL << p)) {
      sol = sol * cur;
    }
    cur = cur * cur;
  }
  int ans = 0;
  for (int i = 0; i < pall; i++) {
    vector<int> a = get(i);
    bool oke = 1;
    for (int k = 0; k < sz; k++) {
      oke = 0;
      for (auto &it : good[k]) {
        if (a[k] % it == 0) {
          oke = 1;
          break;
        }
      }
      if (oke == 0) {
        break;
      }
    }
    if (oke) {
      ans = add(ans, sol[i]);
    }
  }
  cout << ans << "\n";
  return 0;
}

#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define mod 12345

int total, cnt, f[66][205][205], answer[205], news[205], sum[1050], mul[1050];
char dif[205], ch[1050];
bool great[1050], can[1050][205];
vector <int> doing;
map <vector <int>, int> number;

int  Rand()
{
     return (rand() << 15) | rand();
}

void DFS(int current)
{
int  i, size;
bool solved;

     if  (current > total)
     {
         number[doing] = ++cnt;
         size = doing.size();
         solved = true;
         for (i = 0; i < size; i++)
         if  (!can[dif[i + 1]][doing[i]])
         {
             solved = false;
             break;
         }
         if  (solved)
         {
             great[cnt] = true;
         }

         return;
     }
     for (i = 0; i < sum[dif[current]]; i++)
     {
         doing.push_back(i);
         DFS(current + 1);
         doing.pop_back();
     }

     return;
}

int  main()
{
int  all, i, j, k, times, Log, result, current, next, size, temp;
long long n;
vector <int> vec;
map  <vector <int>, int> :: iterator it, it2;

//     freopen("d.in", "r", stdin);
//     freopen("d.out", "w", stdout);

     srand((unsigned) time (0));

     for (i = 'A'; i <= 'Z'; i++)
     {
         sum[i] = 1;
     }

     scanf("%I64d%d\n", &n, &all);
     if  (n == 0 && all == 0)
     {
         printf("1\n");

         return 0;
     }
     if  (n == 0)
     {
         printf("1\n");

         return 0;
     }
     total = 0;
     for (i = 1; i <= all; i++)
     {
         scanf("%c%d\n", &ch[i], &mul[i]);
         sum[ch[i]] *= mul[i];
         dif[++total] = ch[i];
     }

     sort(dif + 1, dif + total + 1);
     for (i = j = 1; i < total; i++)
     if  (dif[i + 1] != dif[j])
     {
         dif[++j] = dif[i + 1];
     }
     total = j;

     for (i = 1; i <= all; i++)
     {
         for (j = 0; j < sum[ch[i]]; j += mul[i])
         {
             can[ch[i]][j] = true;
         }
     }

     doing.clear();
     cnt = 0;
     DFS(1);

     for (it = number.begin(); it != number.end(); it++)
     {
         current = it -> second;
         vec = it -> first;
         size = vec.size();
         for (i = 0; i < size; i++)
         {
             temp = vec[i];
             vec[i] = (vec[i] + 1) % sum[dif[i + 1]];
             it2 = number.find(vec);
             next = it2 -> second;
             f[0][current][next]++;
             vec[i] = temp;
         }
     }

     Log = (int) (log2(n));
     for (times = 1; times <= Log; times++)
     {
         for (i = 1; i <= cnt; i++)
         {
             for (j = 1; j <= cnt; j++)
             {
                 for (k = 1; k <= cnt; k++)
                 {
                     f[times][i][j] += f[times - 1][i][k] * f[times - 1][k][j];
                     f[times][i][j] %= mod;
                 }
             }
         }
     }

     answer[1] = 1;
     for (times = Log; times >= 0; times--)
     if  ((1ll << times) <= n)
     {
         n -= 1ll << times;
         memset(news, 0, sizeof(news));
         for (i = 1; i <= cnt; i++)
         {
             for (j = 1; j <= cnt; j++)
             {
                 news[i] += f[times][i][j] * answer[j];
                 news[i] %= mod;
             }
         }
         memcpy(answer, news, sizeof(answer));
     }

     result = 0;
     for (i = 1; i <= cnt; i++)
     if  (great[i])
     {
         result += answer[i];
         result %= mod;
     }

     printf("%d\n", result);

     return 0;
}

#include <cstring>
#include <fstream>
#include <iostream>
#include <map>
#include <vector>

using namespace std;

const int SIGMA = 26;
const int MOD = 12345;
const int MAX_CONFIGS = 125;

long long n;
int total_configs, sol;
vector<int> restrictions[SIGMA];
int mult[SIGMA];
map<vector<int>, int> config_map;
int mat[MAX_CONFIGS][MAX_CONFIGS], result[MAX_CONFIGS][MAX_CONFIGS];

void ReadInput() {
#ifndef ONLINE_JUDGE
  ifstream cin("d.in");
#endif

  int conditions;
  cin >> n >> conditions;
  for (int i = 0; i < SIGMA; ++i) {
    mult[i] = 1;
  }
  for (int i = 1; i <= conditions; ++i) {
    char letter;
    int multiple;
    cin >> letter >> multiple;
    mult[letter-'A'] *= multiple;
    restrictions[letter-'A'].push_back(multiple);
  }
}

void GenerateConfigurations(int pos, vector<int> &config) {
  if (pos == SIGMA) {
    config_map[config] = ++total_configs;
  } else {
    for (int i = 0; i < mult[pos]; ++i) {
      config.push_back(i);
      GenerateConfigurations(pos+1, config);
      config.pop_back();
    }
  }
}

void BuildMatrix() {
  for (map<vector<int>, int> :: iterator it = config_map.begin(); it != config_map.end(); ++it) {
    vector<int> config = it->first;
    int index = it->second;
    for (int j = 0; j < SIGMA; ++j) {
      if (restrictions[j].size() > 0) {
        int tmp = config[j];
        config[j] = (config[j]+1) % mult[j];
        ++mat[index][config_map[config]];
        config[j] = tmp;
      }
    }
  }
}

void MultiplyMatrix(int a[][MAX_CONFIGS], int b[][MAX_CONFIGS], int c[][MAX_CONFIGS]) {
  int tmp[MAX_CONFIGS][MAX_CONFIGS];
  memset(tmp, 0, sizeof(tmp));
  for (int k = 1; k <= total_configs; ++k) {
    for (int i = 1; i <= total_configs; ++i) {
      for (int j = 1; j <= total_configs; ++j) {
        tmp[i][j] = (tmp[i][j] + b[i][k]*c[k][j]) % MOD;
      }
    }
  }
  memcpy(a, tmp, sizeof(tmp));
}

void RaiseToPower(long long n) {
  for (int i = 1; i <= total_configs; ++i) {
    result[i][i] = 1;
  }

  while (n > 0) {
    if (n&1) {
      MultiplyMatrix(result, result, mat);
    }
    MultiplyMatrix(mat, mat, mat);
    n >>= 1;
  }
}

void CountSolutions() {
  for (map<vector<int>, int> :: iterator it = config_map.begin(); it != config_map.end(); ++it) {
    vector<int> config = it->first;
    int index = it->second;
    int is_valid_config = 1;
    for (int j = 0; j < SIGMA; ++j) {
      if (restrictions[j].size() > 0) {
        int is_multiple = 0;
        for (size_t k = 0; k < restrictions[j].size(); ++k) {
          if (config[j] % restrictions[j][k] == 0) {
            is_multiple = 1;
            break;
          }
        }
        if (!is_multiple) {
          is_valid_config = 0;
          break;
        }
      }
    }
    if (is_valid_config) {
      sol = (sol + result[index][1]) % MOD;
    }
  }
}

int main() {
  ReadInput();
  vector<int> config;
  GenerateConfigurations(0, config);
  BuildMatrix();
  RaiseToPower(n);
  CountSolutions();
  cout << sol << endl;
  return 0;
}

#include <iostream>
#include <cmath>
#include <cstdio>
#include <vector>
#include <set>
#include <algorithm>
#include <string>
#include <cstring>
#include <cstdlib>

using namespace std;

typedef vector< vector< int > > TMatrix;

const int MOD = 12345;

int place(vector< int > &noks, vector< int > &ns) {
    int ans = 0;
    for (int i = 0; i < 26; ++i) {
        if (noks[i] == -1) {
            continue;
        }
        ans = ans * noks[i] + (ns[i] % noks[i]);
    }
    return ans;
}

int nod(int x, int y) {
    if (x == 0) {
        return y;
    }
    return nod(y % x, x);
}

void fill_matrix(TMatrix &matrix, vector< int > &noks, vector< int > &cur, int pr, int i) {
    if (i == 26) {
        int col = place(noks, cur);
        for (int j = 0; j < 26; ++j) {
            if (noks[j] == -1) {
                continue;
            }
            ++cur[j];
            ++matrix[col][place(noks, cur)];
            --cur[j];
        }
        return;
    }

    if (noks[i] == -1) {
        fill_matrix(matrix, noks, cur, pr, i + 1);
    }
    for (int j = 0; j < noks[i]; ++j) {
        cur[i] = j;
        fill_matrix(matrix, noks, cur, pr, i + 1);
    }
    cur[i] = 0;
}

TMatrix E(size_t n) {
    TMatrix res(n, vector<int>(n, 0));
    for (size_t i = 0; i < n; ++i) {
        res[i][i] = 1;
    }
    return res;
}

TMatrix mmul(TMatrix &a, TMatrix &b) {
    int n = a.size();
    TMatrix c(n, vector< int >(n, 0));
    for (int i = 0; i < n; ++i) {
        for (int j = 0; j < n; ++j) {
            for (int k = 0; k < n; ++k) {
                c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % MOD;
            }
        }
    }
    return c;
}

TMatrix deg(TMatrix &matrix, long long n) {
    if (n == 0) {
        return E(matrix.size());
    }

    TMatrix res = deg(matrix, n / 2);
    res = mmul(res, res);
    if (n % 2 == 1) {
        res = mmul(res, matrix);
    }

    return res;
}

int count_answer(TMatrix &matrix, vector< int > &noks, vector< vector< int > > &res,
                 vector< int > &cur, int i) {
    if (i == 26) {
        int ans = 0;
        int type = place(noks, cur);
        return matrix[type][0];
    }

    int ans = 0;
    if (noks[i] == -1) {
        return count_answer(matrix, noks, res, cur, i + 1);
    }
    for (int j = 0; j < noks[i]; ++j) {
        bool ok = false;
        for (size_t k = 0; k < res[i].size(); ++k) {
            if (j % res[i][k] == 0) {
                ok = true;
                break;
            }
        }
        if (ok) {
            cur[i] = j;
            ans = (ans + count_answer(matrix, noks, res, cur, i + 1)) % MOD;
        }
    }

    cur[i] = 0;
    return ans;
}

int main() {
    long long n;
    int k;
    cin >> n >> k;
    vector< vector< int > > res(26);
    vector< int > noks(26, -1);
    vector< int > cur(26, 0);
    int pr = 1;
    for (int i = 0; i < k; ++i) {
        string s;
        int x;
        cin >> s >> x;
        int type = s[0] - 'A';
        if (x == 1) {
            res[type].clear();
            noks[type] = 1;
        }
        if (noks[type] == -1) {
            noks[type] = 1;
        }
        noks[type] *= x;
        pr *= x;
        res[type].push_back(x);
    }

    TMatrix matrix(pr, vector< int >(pr, 0));

    fill_matrix(matrix, noks, cur, pr, 0);
    TMatrix fmatrix = deg(matrix, n);

    int ans = count_answer(fmatrix, noks, res, cur, 0);
    cout << ans << '\n';

    return 0;
}

#define LLD "%I64d"

#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstdlib>
#include<cstring>

typedef long long ll;

const int fin=0,maxn=1002,maxk=125;
const int MC=12345;
ll N;
int M,m;
bool vis[27],fun[27],g[27];
int T[maxn],c[maxn],d[maxn];

struct pt{
  int x,y;
  pt(){}
  pt(const int &x,const int &y):x(x),y(y){}
}a[maxn],b[maxn];

struct mat{
  int n,m,a[maxk][maxk];
  mat(){memset(a,0,sizeof(a));}
  mat(const int &n,const int &m):n(n),m(m){memset(a,0,sizeof(a));}
  int& operator()(const int &x,const int &y){return a[x][y];}
}A,D;
mat operator *(mat a,mat b){
  mat c(a.n,b.m);
  for(int i=0;i<a.n;++i)
    for(int j=0;j<b.m;++j)
      for(int k=0;k<a.m;++k)
        c(i,j)=(c(i,j)+a(i,k)*b(k,j))%MC;
  return c;
}
mat pow(mat a,ll n){
  mat b(a.n,a.n);
  for(int i=0;i<a.n;++i)b(i,i)=1;
  while(n){
    if(n&1)b=b*a;
    a=a*a;
    n>>=1;
  }
  return b;
}

int main(){
  if(fin){
    freopen("t.in","r",stdin);
    freopen("t.out","w",stdout);
  }
  char ch;
  int x,y,t,s,i,j,k;
  scanf(LLD" %d\n",&N,&M);
  while(M--){
    scanf("%c %d\n",&ch,&y),x=ch-'A';
    if(y==1)fun[x]=1;
    else b[m++]=pt(x,y);
    vis[x]=1;
  }
  for(M=m,m=i=0;i<M;++i)
    if(!fun[b[i].x])a[m++]=b[i];
  for(T[m]=1,i=m-1;i>=0;--i)
    T[i]=T[i+1]*a[i].y;
  D.n=D.m=T[0];
  for(i=0;i<T[0];++i){
    for(t=i,j=0;j<m;++j)
      c[j]=t/T[j+1],t%=T[j+1];
    for(j=0;j<26;++j)
      if(vis[j]){
        for(s=k=0;k<m;++k)
          s+=(c[k]+(a[k].x==j))%a[k].y*T[k+1];
        D(i,s)=(D(i,s)+1)%MC;
        //printf("%d %d\n",i,s);
      }
  }
  A.n=1,A.m=T[0];
  A(0,0)=1;
  D=pow(D,N);
  A=A*D;
  for(s=0,i=0;i<T[0];++i){
    memset(g,0,sizeof(g));
    for(t=i,j=0;j<m;++j){
      if(t/T[j+1]==0)g[a[j].x]=1;
      t%=T[j+1];
    }
    for(j=0;j<26;++j)
      if(vis[j]&&!fun[j])
        if(!g[j])break;
    if(j==26){
      s=(s+A(0,i))%MC;
      //printf("%d\n",i);
    }
  }
  printf("%d",s);
  return 0;
}

#include <bits/stdc++.h>
#ifdef _MSC_VER
#define __builtin_popcount (int)__popcnt
#define __builtin_popcountll (int)__popcnt64
#define __builtin_clz (int)__lzcnt
#define $ system("pause")
#define gp_hash_table unordered_map
#else
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define $
//#define USACO
//#define IOI_style
#endif

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double ld;
typedef complex<double> point;

#define MOD 12345
#define MAXN 123
#define LG 20
#define inf int(1e9 + 100)

#define rep(i, j, k) for (int i = j; i < k; i++)
#define for_all(x) x.begin(), x.end()
#define lid id << 1
#define rid id << 1 | 1
#define lch l, mid, lid
#define rch mid, r, rid
#define pb push_back
#define X first
#define Y second
#define re real()
#define im imag()

template <typename S, typename T>
inline ostream &operator<<(ostream &out, const pair<S, T> &p)
{
	return out << "( " << p.X << " , " << p.Y << " )";
}
template <typename S>
inline ostream &operator<<(ostream &out, const vector<S> &p)
{
	for (auto &e : p) out << e; return out;
}
template <typename T, typename S>
inline T smin(T &a, const S &b) { return a > b ? a = b : a; }
template <typename T, typename S>
inline T smax(T &a, const S &b) { return a < b ? a = b : a; }
inline double dot(const point l, const point r) { return l.re * r.re + l.im * r.im; }
inline double cross(const point l, const point r) { return l.re * r.im - l.im * r.re; }
ll po(ll v, ll u) { return u ? (po(v * v % MOD, u >> 1) * (u & 1 ? v : 1) % MOD) : 1; }
template<class T> inline void add(T &l, const T &r) { l = (l + r) % MOD; }
ll gcd(ll v, ll u) { return u ? gcd(u, v % u) : v; }

ll n;
int c;
vector<int> vec, o[30];

struct Mat {
	int n, m;
	ll arr[MAXN][MAXN];
	Mat(int n, int m, int z = 0) : n(n), m(m) {
		memset(arr, 0, sizeof(arr));
		rep(i, 0, min(n, m))
			arr[i][i] = z;
	}
};

inline ostream &operator<<(ostream &out, Mat &p)
{
	rep(i, 0, p.n) {
		rep(j, 0, p.m)
			cout << p.arr[i][j] << ' ';
		cout << endl;
	}
	return out;
}

inline Mat operator*(Mat l, Mat r) {
	Mat res(l.n, r.m);
	rep(i, 0, res.n) rep(j, 0, res.m) rep(k, 0, l.m)
		res.arr[i][j] += l.arr[i][k] * r.arr[k][j];
	rep(i, 0, res.n) rep(j, 0, res.m) res.arr[i][j] %= MOD;
	return res;
}

Mat operator^ (const Mat & v, ll u)
{
	Mat res(v.n, v.m, 1);
	for (int i = 62; ~i; i--) {
		res = res * res;
		if (u & (1ll << i)) res = res * v;
	}
	return res;
}

vector<int> state, f[MAXN];
map<vector<int>, int> rf;
int NOW, sz[MAXN];
void build(int g = 0) {
	if (g == c) {
		f[NOW] = state;
		rf[state] = NOW++;
		return;
	}
	rep(i, 0, sz[vec[g]]) {
		state[g] = i;
		build(g + 1);
	}
	return;
}

#ifndef IOI_style
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
#ifdef USACO
	freopen("gathering.in", "r", stdin);
	freopen("gathering.out", "w", stdout);
#endif
	cin >> n >> c;
	rep(i, 0, c) {
		char v; int m;
		cin >> v >> m;
		v -= 'A';
		vec.pb(v);
		o[v].pb(m);
	}
	sort(for_all(vec));
	vec.resize(unique(for_all(vec)) - vec.begin());
	for (auto e : vec) {
		sort(for_all(o[e]));
		o[e].resize(unique(for_all(o[e])) - o[e].begin());
		sz[e] = 1;
		for (auto z : o[e]) sz[e] *= z / gcd(z , sz[e]);
	}
	state.resize(vec.size());
	c = vec.size(); build();
	Mat M(NOW, NOW);
	rep(i, 0, NOW) {
		auto v = f[i];
		rep(j, 0, c) {
			v[j] = (v[j] + 1) % sz[vec[j]];
			M.arr[rf[v]][i]++;
			v[j] = (v[j] - 1 + sz[vec[j]]) % sz[vec[j]];
		}
	}
	M = M ^ n;
	ll answer = 0;
	rep(i, 0, NOW) {
		auto v = f[i];
		bool bad = false;
		rep(j, 0, c) {
			bool flag = false;
			for (auto z : o[vec[j]])
				if (v[j] % z == 0) flag = true;
			if (!flag) bad = true;
		}
		if (bad) continue;
		add(answer, M.arr[i][0]);
	}
	cout << answer << endl;
	$;
	return 0;
}
#endif

#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cctype>
#include <iomanip>
#include <bitset>
#include <list>
#include <deque>
#include <utility>
#include <functional>
#include <cassert>
#include <complex>

using namespace std;

#define all(a)              (a).begin(), (a).end()
#define ms(a,b)             memset(a, b, sizeof(a))
#define mp                  make_pair
#define pb                  push_back
#define fore(it,a)          for (auto it = (a).begin(), it##_ = (a).end(); it != it##_; ++it)
#define f0r(i, a)           for (int i = 0, i##_ = (a); i < i##_; ++i)
#define debug(args...)      do {cerr << #args << ": "; dbg,args; cerr << endl;} while(0)
#define read(type, args...) type args; rdr,args;
#define fi                  first
#define se                  second
#define bit_no              __builtin_popcount
#define left(a)             (2*(a))
#define right(a)            (2*(a)+1)
#define mid(left, right)    (((left)+(right))/2+1)
#define PI                  acos(-1)

typedef long long               ll;
typedef long double             ld;
typedef unsigned long long      ull;
typedef vector<int>             vi;
typedef vector<vi>              vvi;
typedef pair<int, int>          ii;
typedef tuple<int, int, int>    iii;
typedef vector<ii>              vii;
typedef vector<iii>             viii;

template<typename T>
using min_pq = priority_queue<T, vector<T>, greater<T>>;

const int inf = 2e8+5;
const ll l_inf = 9e18+5;
const int mod_v = 12345;
const int max_n = 1e5+5;

template<typename T>
T gcd(T a, T b)
{
    while (b) {
        T temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}

template<typename T>
tuple<T, T, T> egcd(T a, T b)
{
    T x1 = 1, x2 = 0, y1 = 0, y2 = 1;
    while (b) {
        T q = a / b, r = a % b;
        T new_x = x1 - q*x2, new_y = y1 - q*y2;
        x1 = x2, y1 = y2, x2 = new_x, y2 = new_y;
        a = b, b = r;
    }
    return make_tuple(a, x1, y1);
}

inline ll lcm(ll a, ll b)
{
    return a*b/gcd(a, b);
}

template<typename T>
inline T mod(T a, T b = mod_v)
{
    return (a % b + b) % b;
}

template<typename T>
inline T mod_inv(T a, T b = mod_v)
{
    return mod(get<1>(egcd(a, b)), b);
}

template<typename T>
inline T sum(T a, T b, T m = mod_v)
{
    return mod(mod(a, m) + mod(b, m), m);
}

template<typename T>
inline T difference(T a, T b, T m = mod_v)
{
    return mod(mod(a, m) - mod(b, m), m);
}

inline ll product(ll a, ll b, ll m = mod_v)
{
    return mod(mod(a, m) *  mod(b, m), m);
}

inline ll quotient(ll a, ll b, ll m = mod_v)
{
    return mod(mod(a, m) * mod_inv(b, m), m);
}

template<typename T,typename T2>
ostream& operator<< (ostream &s, const pair<T,T2> &p) {return s << p.fi << ' ' << p.se << ' ';}

template<typename T,typename T2>
istream& operator>> (istream &s, pair<T,T2> &p) {return s >> p.fi >> p.se;}

template<typename T>
ostream& operator<< (ostream &s, const vector<T> &v)  {for (auto it: v) s << it << ' '; return s;}

template<typename T>
istream& operator>> (istream &s, vector<T> &v) {fore (it, v) s >> *it; return s;}

template<typename T>
void read_range(T beg, T end)
{
    while (beg != end)
        cin >> *beg++;
}

template<typename T>
void print_range(T beg, T end)
{
    while (beg != end)
        cout << *beg++ << ' ';
}

struct reader
{
    template<typename T>
    reader& operator, (T &v)
    {
        cin >> v;
        return *this;
    }
} rdr;

struct debugger
{
    template<typename T>
    debugger& operator, (const T &v)
    {
        cerr << v << ", ";
        return *this;
    }
} dbg;

/***************************************************************
----------------------------------------------------------------
----------------------------------------------------------------
***************************************************************/

int ar[123][123];
int res[123][123];
int temp[123][123];
int mult[26];
int hash_mult[27];
vi mult2[26];

void prod(int a[][123], const int b[][123])
{
    f0r (i, hash_mult[26])
        f0r (j, hash_mult[26]) {
            temp[i][j] = 0;
            f0r (k, hash_mult[26])
                temp[i][j] = (temp[i][j] + a[i][k] * b[k][j]) % mod_v;
        }
    memcpy(a, temp, sizeof(temp));
}

void power(ll p)
{
    f0r (i, hash_mult[26])
        res[i][i] = 1;
    while (p) {
        if (p & 1)
            prod(res, ar);
        prod(ar, ar);
        p >>= 1;
    }
}

void init_hash()
{
    f0r (i, 27) {
        if (i == 0) hash_mult[i] = 1;
        else hash_mult[i] = (hash_mult[i-1] * max(1, mult[i-1]));
    }
}

bool correct(int i) {
    f0r (j, 26)
        if (mult[j]) {
            int cur_cnt = (i / hash_mult[j]) % mult[j];
            bool ok = false;
            for (int m : mult2[j])
                if (cur_cnt % m == 0) ok = true;
            if (!ok) return false;
        }

    return true;
}

void init_ar()
{
    f0r (i, hash_mult[26]) {
        f0r (j, 26)
            if (mult[j]) {
                int cur_cnt = (i / hash_mult[j]) % mult[j];
                int new_cnt = (cur_cnt + 1) % mult[j];
                int new_s_no = i + (new_cnt - cur_cnt) * hash_mult[j];

                ar[i][new_s_no]++;
            }
    }
}

int main()
{
    ios_base::sync_with_stdio(false);

    read(ll, n);
    read(int, c);

    f0r (i, c) {
        read(char, ch);
        read(int, m);
        if (mult[ch - 'A'] == 0)
            mult[ch - 'A'] = m;
        else
            mult[ch - 'A'] = lcm(mult[ch - 'A'], m);
        mult2[ch - 'A'].pb(m);
    }

    init_hash();
    init_ar();

    power(n);

    int r = 0;
    f0r (i, hash_mult[26])
        if (correct(i))
            r = (r + res[0][i]) % mod_v;

    cout << r;

    return 0;
}

#include<bits/stdc++.h>
using namespace std;
const int maxn = 125;
const int mod = 12345;
long long n;
char s[3];
int m,mu[maxn],p[26][maxn],vis[maxn],f[maxn][maxn],bas[maxn],g[maxn][maxn],ans[maxn],res[maxn],c;

int main()
{
    scanf("%lld%d",&n,&m);
    for(int i=0;i<26;i++)
        vis[i]=0,mu[i]=1;
    for(int i=0;i<m;i++){
        scanf("%s%d",s,&c);
        mu[s[0]-'A']*=c;
        p[s[0]-'A'][c]=1;
        vis[s[0]-'A']=1;
    }
    bas[0]=1;
    for(int i=1;i<=26;i++)
        bas[i]=bas[i-1]*mu[i-1];
    int t=bas[26];
    for(int i=0;i<t;i++)
        for(int j=0;j<26;j++)
            if(vis[j])
                f[i][i+bas[j]-(i%bas[j+1]/bas[j]+1!=mu[j]?0:bas[j+1])]++;
    ans[0]=1;
    for(;n;n>>=1){
        if(n%2==1){
            memset(res,0,sizeof(res));
            for(int i=0;i<t;i++)
            for(int j=0;j<t;j++){
                res[j]+=ans[i]*f[i][j];
                res[j]%=mod;
            }
            for(int i=0;i<t;i++)
                ans[i]=res[i];
        }
        memset(g,0,sizeof(g));
        for(int i=0;i<t;i++)
        for(int j=0;j<t;j++)
        for(int k=0;k<t;k++)
        {
            g[i][k]+=f[i][j]*f[j][k];
            g[i][k]%=mod;
        }
        for(int i=0;i<bas[26];i++)
            for(int j=0;j<bas[26];j++)
                f[i][j]=g[i][j];
    }
    int Ans = 0;
    for(int i=0;i<t;i++){
        for(int j=0;j<26;j++){
            if(vis[j]){
                int flag=0;
                for(int k=1;k<=bas[26];k++){
                    if(p[j][k]&&i%bas[j+1]/bas[j]%k==0)
                        flag=1;
                }
                if(!flag)break;
            }
            if(j==25)(Ans+=ans[i])%=mod;
        }
    }
    cout<<Ans<<endl;
}

#include <stdio.h>
#include <cstring>
#include <iostream>
#include <vector>
#include <map>
using namespace std;

typedef long long ll;
const int MOD = 12345;
const int MAXN = 1100;
int maxv[30];
vector <int> G[30], ans;
ll m; int n, cntv;

struct Matrix{
	ll map[125][125];
	Matrix operator * (const Matrix &b) const {
		Matrix c; memset(c.map, 0, sizeof(c.map));
		for(int i = 1; i <= cntv; ++ i) for(int j = 1; j <= cntv; ++ j)
		for(int k = 1; k <= cntv; ++ k) c.map[i][j] = (c.map[i][j] + map[i][k] * b.map[k][j]) % MOD;
		return c;
	}
}M, rnt;

struct Node{
	int a[30];
	bool operator < (const Node &b) const {
		for(int i = 1; i <= 26; ++ i)
			if(a[i] != b.a[i]) return a[i] < b.a[i];
		return 0;
	}
}t;

map <Node, int> hsh;

bool Check(Node t){
	for(int i = 1; i <= 26; ++ i){
		if(maxv[i] == 0) continue;
		bool flag = false;
		for(int j = 0; j < G[i].size(); ++ j)
			if(t.a[i] % G[i][j] == 0){
				flag = true;
				break;
			}
		if(!flag) return false;
	}
	return true;
}

void DFS(int u){
	if(u == 27){
		hsh[t] = ++ cntv;
		if(Check(t)) ans.push_back(cntv);
		return;
	}
	if(maxv[u] == 0) t.a[u] = 0, DFS(u + 1);
	else{
		for(int i = 0; i < maxv[u]; ++ i)
			t.a[u] = i, DFS(u + 1);
	}
}

void Pow(ll k){
	for(int i = 1; i <= cntv; ++ i) rnt.map[i][i] = 1;
	while(k){
		if(k & 1) rnt = rnt * M;
		M = M * M;
		k >>= 1;
	}
}

int main(){
	scanf("%lld%d", &m, &n);
	char c; int x;
	for(int i = 1; i <= n; ++ i){
		scanf(" %c%d", &c, &x);
		G[c - 'A' + 1].push_back(x);
		if(maxv[c - 'A' + 1]) maxv[c - 'A' + 1] *= x;
		else maxv[c - 'A' + 1] = x;
	}
	if(m == 0){ printf("1"); return 0; }
	if(n == 0){ printf("0"); return 0; }
	Node cur, nxt;
	int v1, v2;
	DFS(1);
	for(map <Node, int>::iterator i = hsh.begin(); i != hsh.end(); ++ i){
		cur = i -> first;
		v1 = i -> second;
		for(int j = 1; j <= 26; ++ j){
			if(maxv[j] == 0) continue;
			nxt = cur; nxt.a[j] = (nxt.a[j] + 1) % maxv[j];
			v2 = hsh[nxt]; M.map[v2][v1] ++;
		}
	}
	Pow(m);
	int sumv = 0;
	for(int i = 0; i < ans.size(); ++ i) sumv = (sumv + rnt.map[ans[i]][1]) % MOD;
	printf("%d\n", sumv);
	return 0;
}

#include <bits/stdc++.h>
using namespace std;
#define PB push_back
#define ZERO (1e-10)
#define INF int(1e9+1)
#define CL(A,I) (memset(A,I,sizeof(A)))
#define DEB printf("DEB!\n");
#define D(X) cout<<"  "<<#X": "<<X<<endl;
#define EQ(A,B) (A+ZERO>B&&A-ZERO<B)
typedef long long ll;
typedef pair<ll,ll> pll;
typedef vector<int> vi;
typedef pair<int,int> ii;
typedef vector<ii> vii;
#define IN(n) int n;scanf("%d",&n);
#define FOR(i, m, n) for (int i(m); i < n; i++)
#define F(n) FOR(i,0,n)
#define FF(n) FOR(j,0,n)
#define FT(m, n) FOR(k, m, n)
#define aa first
#define bb second
void ga(int N,int *A){F(N)scanf("%d",A+i);}
#define MM (1001)
void mul(int A[MM][MM],int B[MM][MM],int R[MM][MM],int W,int M){
    F(W)FF(W)R[i][j]=0;
    F(W)FF(W){
        ll D=M*1ll*M,S=0;;
        FT(0,W)if((S+=A[i][k]*1ll*B[k][j])>=D)S-=D;
        R[i][j]=S%M;
    }
}
void pw(int M[MM][MM],int R[MM][MM],int W,ll k,int MD){
    static int E[MM][MM],H[MM][MM];
    F(W)FF(W)R[i][j]=E[i][j]=i==j;
    while(k){
        if(k&1)mul(E,M,R,W,MD),memcpy(E,R,sizeof(E));
        mul(M,M,H,W,MD);
        memcpy(M,H,sizeof(H));
        k>>=1;
    }
}
int lcm(int a,int b){return  a/__gcd(a,b)*b;}
vi o[26];
char c;
ll N;
int Q,a,C;
void nrm(vi&o){
    F((int)o.size()){
        bool x=0;
        FF((int)o.size())if(i^j&&!(o[i]%o[j]))x=1;
        if(x)o[i]=o.back(),o.pop_back(),--i;
    }
}
int mp(vi&o){return accumulate(o.begin(),o.end(),1,lcm);}
#define MOD 12345
int M[MM][MM],R[MM][MM],L[26];
bool dv(int I,vi&o){for(auto&h:o)if(!(I%h))return 1;return o.empty();}
map<vi,int> T;
void rec(int u,vi r,bool x,int l){
    if(u==26){
        if(!T.count(r))T[r]=C++;
        int I=T[r];
        if(x)M[I][l]=1;
        F(26)if(!o[i].empty()){
            ++r[i]%=L[i];
            if(!T.count(r))T[r]=C++;
            ++M[I][T[r]];
            r[i]+=L[i]-1,r[i]%=L[i];
        }
        return;//TODO
    }
    r.PB(-1);
    F(L[u])r.back()=i,rec(u+1,r,x&dv(i,o[u]),l);
}
int go(ll N){
    CL(M,0);
    int l=1;
    F(26)l*=mp(o[i]);
    vi r;
    rec(0,r,1,l);
    ++l;
//    F(l)FF(l)printf("%d%c",M[i][j],j+1==l?10:32);
    pw(M,R,l,N+1,MOD);
    return R[0][l-1];
}
int main(void){
    scanf("%lld%d",&N,&Q);
    F(Q)scanf(" %c%d",&c,&a),o[c-65].PB(a);
    F(26)nrm(o[i]),L[i]=mp(o[i]);
//    D(go(N))//TODO ERASE
//    D(go(N-1))
//    printf("%d\n",(go(N)-go(N-1)+MOD)%MOD);
    printf("%d\n",go(N));
    return 0;
}//This shall not work.. actually no idea why it passes samples :'(

#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 <cstring>
#include <cassert>
#include <cstdlib>
#include <ctime>

using namespace std;
typedef long long int64;
#ifdef HOME
	#define E(c) cerr<<#c
	#define Eo(x) cerr<<#x<<" = "<<(x)<<endl
	#define Ef(...) fprintf(stderr, __VA_ARGS__)
#else
	#define E(c) ((void)0)
	#define Eo(x) ((void)0)
	#define Ef(...) ((void)0)
#endif

int MOD = 12345;
inline void mdadd(int &a, int b) { a += b; if (a >= MOD) a -= MOD; }

typedef map<vector<int>, int> StateMap;
StateMap stMap;

int64 k;
int n, m, s;
bool has[32];
int p[32];
bool can[32][128];

vector<int> curr;
void DoStates(int u) {
	if (u == n) {
		int tt = stMap.size();
		stMap[curr] = tt;
		return;
	}
	for (int j = 0; j<p[u]; j++) {
		curr[u] = j;
		DoStates(u+1);
	}
}

struct Matrix {
	int a[128][128];
};
Matrix operator*(const Matrix &x, const Matrix &y) {
	Matrix res;
	for (int i = 0; i<s; i++)
		for (int j = 0; j<s; j++) {
			res.a[i][j] = 0;
			for (int u = 0; u<s; u++)
				res.a[i][j] = (res.a[i][j] + x.a[i][u] * y.a[u][j]) % MOD;
		}
	return res;
}

Matrix mdpow(Matrix a, int64 p) {
	Matrix r;
	for (int i = 0; i<s; i++) for (int j = 0; j<s; j++) r.a[i][j] = i==j;
	Matrix x = a;
	for (; p; p>>=1) {
		if (p & 1) r = r * x;
		x = x * x;
	}
	return r;
}

Matrix trans;
bool good[128];

int main() {
#ifdef HOME
	freopen("input.txt", "r", stdin);
	freopen("output.txt", "w", stdout);
#endif
	n = 26;
	scanf("%I64d%d", &k, &m);
	for (int i = 0; i<m; i++) {
		char c;
		int a;
		scanf(" %c%d", &c, &a);
		int t = c - 'A';

		if (!has[t]) {
			has[t] = true;
			p[t] = 1;
		}
		for (int j = 0; j<128; j += a)
			can[t][j] = true;
		p[t] *= a;
	}

	int nn = 0;
	s = 1;
	for (int i = 0; i<n; i++)
		if (has[i]) {
            p[nn] = p[i];
			memcpy(can[nn], can[i], sizeof(can[0]));
			s *= p[nn];
		    nn++;
		}
	n = nn;

	if (n == 0) {
		printf("%d\n", k==0 ? 1 : 0);
		return 0;
	}

	curr.resize(n);
    DoStates(0);
    assert(stMap.size() == s);

	for (StateMap::iterator it = stMap.begin(); it != stMap.end(); it++) {
		const vector<int> &curr = it->first;

		good[it->second] = true;
		for (int i = 0; i<n; i++) if (!can[i][curr[i]])
			good[it->second] = false;

		for (int i = 0; i<n; i++) {
			vector<int> next = curr;
			next[i]++;
			if (next[i] == p[i]) next[i] = 0;
			mdadd(trans.a[it->second][stMap[next]], 1);
		}
	}

	Matrix pp = mdpow(trans, k);
	int ans = 0;
	for (int i = 0; i<s; i++) if (good[i])
		mdadd(ans, pp.a[0][i]);

	printf("%d\n", ans);

	return 0;
}

#include <algorithm>
#include <bitset>
#include <complex>
#include <deque>
#include <exception>
#include <fstream>
#include <functional>
#include <iomanip>
#include <ios>
#include <iosfwd>
#include <iostream>
#include <istream>
#include <iterator>
#include <limits>
#include <list>
#include <locale>
#include <map>
#include <memory>
#include <new>
#include <numeric>
#include <ostream>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <stdexcept>
#include <streambuf>
#include <string>
#include <typeinfo>
#include <utility>
#include <valarray>
#include <vector>
#if __cplusplus >= 201103L
#include <array>
#include <atomic>
#include <chrono>
#include <condition_variable>
#include <forward_list>
#include <future>
#include <initializer_list>
#include <mutex>
#include <random>
#include <ratio>
#include <regex>
#include <scoped_allocator>
#include <system_error>
#include <thread>
#include <tuple>
#include <typeindex>
#include <type_traits>
#include <unordered_map>
#include <unordered_set>
#endif

#define ll int
#define pb push_back
#define ld long double
#define mp make_pair
#define F first
#define S second
#define pii pair<ll,ll>

using namespace :: std;

const ll maxn=205;
const ll maxn2=125;
const ll mod=12345;

struct M
{
	int a[maxn2][maxn2];
};

M ham,sefr,res;

void operator *=(M &a,const M &b){
	memset(res.a,0,sizeof res.a);
	for(short i=0;i<maxn2;i++){
		for(short k=0;k<maxn2;k++){
			for(short j=0;j<maxn2;j++){
				res.a[i][j]=(res.a[i][j]+a.a[i][k]*b.a[k][j])%mod;
			}
		}
	}
	swap(a.a,res.a);
}
M operator ^(M a,long long n){
	M ans=ham;
	while(n){
		if(n&1){
			ans*=a;
		}
		n>>=1;
		a*=a;
	}
	return ans;
}
void bild_matrix(){
	for(ll i=0;i<maxn2;i++)for(ll j=0;j<maxn2;j++)sefr.a[i][j]=0;
	ham=sefr;
	for(ll i=0;i<maxn2;i++)ham.a[i][i]=1;
}
void pri(M base,ll bigZ){
	for(ll i=0;i<bigZ;i++){
		for(ll j=0;j<bigZ;j++){
			cout<<base.a[i][j]<<" ";
		}
		cout<<endl;
	}
}

vector<ll> ves[26];
ll cnt=0;
ll z[26];

int main(){
	bild_matrix();
	ios_base::sync_with_stdio(0);cin.tie(0);cout.tie(0);
	ll c,web=0;
	long long n;
	cin>>n>>c;
	{
		vector<ll> vec[26];
		bool chert[26];
		for(ll i=0;i<c;i++){
			char s;
			cin>>s;
			ll b;
			cin>>b;
			if(b==1){
				chert[s-'A']=1;
			}
			vec[s-'A'].pb(b);
		}
		for(ll i=0;i<26;i++){
			if(vec[i].size() && !chert[i]){
				ves[cnt++]=vec[i];
			}
			if(chert[i])web++;
		}
	}
	ll bigZ=1;
	for(ll i=0;i<cnt;i++){
		z[i]=1;
		for(auto u:ves[i]){
			z[i]*=u;
		}
		bigZ*=z[i];
	}
	M base=sefr;
	for(ll i=0;i<bigZ;i++){
		for(ll j=0;j<bigZ;j++){
			ll I[26];
			ll J[26];
			ll res=i;
			for(ll k=0;k<cnt;k++){
				I[k]=res%z[k];
				res/=z[k];
			}
			res=j;
			for(ll k=0;k<cnt;k++){
				J[k]=res%z[k];
				res/=z[k];
			}
			ll dif=0;
			for(ll k=0;k<cnt;k++){
				if(I[k]!=J[k]){
					dif++;
					if((I[k]+1)%z[k]!=J[k]){
						dif++;
						break;
					}
				}
			}
			if(dif==0){
				base.a[i][j]=web;
			}
			if(dif==1){
				base.a[i][j]=1;
			}
		}
	}

	M ans=base^n;
	long long an=0;
	for(ll i=0;i<bigZ;i++){
		ll I[26];
		ll res=i;
		for(ll k=0;k<cnt;k++){
			I[k]=res%z[k];
			res/=z[k];
		}
		bool good=1;
		for(ll k=0;k<cnt;k++){
			bool bd=0;
			for(auto v:ves[k]){
				if(I[k]%v==0){
					bd=1;
				}
			}
			good&=bd;
		}
		if(good){
			an+=ans.a[0][i];
		}
	}
	an%=mod;
	cout<<an;
}

#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <bitset>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstring>
using namespace std;

#define MP make_pair
#define PB push_back
#define two(X) (1<<(X))
#define SIZE(A) ((int)(A.size()))
#define LENGTH(A) ((int)A.length())
#define random(x) (rand()%x)
#define randomize() (srand((int)time(0)))

typedef long long int64;
typedef vector<int> VI;
typedef vector<string> VS;

const int maxn=26;
const int INF=0x7FFFFFFF;
const int Mod=12345;
const double eps=1e-10;
const double pi=acos(-1.0);

class Tmatrix
{
	public:
        int n,m;
        int mat[128][128];

		Tmatrix operator *(const Tmatrix &b)
		{
			Tmatrix ret;
			memset(ret.mat,0,sizeof(ret.mat));
			for (int i=0; i<n; i++)
				for (int j=0; j<b.m; j++)
                    for (int k=0; k<m; k++)
                        ret.mat[i][j]=(ret.mat[i][j]+mat[i][k]*b.mat[k][j])%Mod;
			ret.n=n; ret.m=b.m;
			return ret;
		}
};

Tmatrix ans,basic,tmp;
int64 n;
bool can[26],exist[26];
char ch[1001];
int m,MAX_N;
int rem[1001],num[1001];

Tmatrix calc(int64 n)
{
	if (n==1) return basic;
	tmp=calc(n/2);
	tmp=tmp*tmp;
	if (n&1) tmp=tmp*basic;
	return tmp;
}

void init()
{
	memset(exist,0,sizeof(exist));
	cin>>n>>m;
	MAX_N=1;
	for (int i=0; i<m; i++)
	{
		cin>>ch[i]>>num[i];
		exist[ch[i]-'A']=true;
		MAX_N*=num[i];
	}
}

void solve()
{
	memset(basic.mat,0,sizeof(basic.mat));
	basic.n=MAX_N; basic.m=MAX_N;
	for (int i=0; i<MAX_N; i++)
	{
		int tmp=i;
		for (int j=0; j<m; j++)
		{
			rem[j]=tmp%num[j];
			tmp/=num[j];
		}

		for (int j=0; j<26; j++)
			if (exist[j])
			{
				for (int k=0; k<m; k++)
					if (j==(ch[k]-'A'))
						rem[k]=(rem[k]+1)%num[k];
				int next=0;
				for (int k=m-1; k>=0; k--)
					next=next*num[k]+rem[k];
				++basic.mat[i][next];
				for (int k=0; k<m; k++)
					if (j==(ch[k]-'A'))
						rem[k]=(rem[k]-1+num[k])%num[k];
			}
	}

	if (n>0) ans=calc(n);
	int ret=0;
	for (int i=0; i<MAX_N; i++)
	{
		int tmp=i;
		memset(can,0,sizeof(can));
		for (int j=0; j<m; j++)
		{
			rem[j]=tmp%num[j];
			if (rem[j]==0) can[ch[j]-'A']=true;
			tmp/=num[j];
		}
		bool flag=true;
		for (int j=0; j<26; j++)
			if (exist[j] && !can[j])
			{
				flag=false;
				break;
			}
		if (flag) ret=((ret+ans.mat[0][i])%Mod);
	}
	if (n==0) cout<<1<<endl; else cout<<ret<<endl;
}

int main()
{
	init();
	solve();
	return 0;
}

#include <cstdio>

using namespace std;

const int MAXN = 1000;
const int MAXM = 123;
const int MOD = 12345;

int f[26], cnt = 1;
int t[MAXN], p[MAXN], a[MAXN];
int d[MAXM][MAXM], e[MAXM][MAXM];
long long n;
int m, c;

int multi(int a[MAXM][MAXM], int b[MAXM][MAXM])
{
    int c[MAXM][MAXM];
    for (int i = 0; i < m; i++)
        for (int j = 0; j < m; j++)
        {
            long long res = 0;
            for (int k = 0; k < m; k++)
                res += a[i][k] * b[k][j];
            c[i][j] = res % MOD;
        }
    for (int i = 0; i < m; i++)
        for (int j = 0; j < m; j++)
            a[i][j] = c[i][j];
    return 0;
}

int main()
{
    #ifndef ONLINE_JUDGE
        freopen("in", "r", stdin);
        freopen("out", "w", stdout);
    #endif
    scanf("%I64d %d\n", &n, &c);
    m = 1;
    for (int i = 0; i < c; i++)
    {
        char c;
        scanf("%c %d\n", &c, &p[i]);
        f[t[i] = c - 'A'] = cnt;
        m *= p[i];
    }

    for (int i = 0, x; i < m; i++)
    {
        x = i;
        for (int j = 0; j < c; j++)
        {
            a[j] = x % p[j];
            x /= p[j];
        }

        for (int j = 0; j < 26; j++)
            if (f[j] == cnt)
            {
                x = 0;
                for (int k = c - 1; k >= 0; k--)
                    (x *= p[k]) += (a[k] + (t[k] == j)) % p[k];
                d[i][x]++;
            }
    }

    for (int i = 0; i < m; i++)
        e[i][i] = 1;

    while (n)
    {
        if (n & 1) multi(e, d);
        if (n >>= 1) multi(d, d);
    }

    int ans = 0;
    for (int i = 0, x; i < m; i++)
    {
        cnt++;
        x = i;
        for (int j = 0; j < c; j++)
        {
            if (x % p[j] == 0)
                f[t[j]] = cnt;

            x /= p[j];
        }

        bool flag = true;
        for (int j = 0; j < 26 && flag; j++)
            flag = f[j] == 0 || f[j] == cnt;

        if (flag)
            (ans += e[0][i]) %= MOD;
    }
    printf("%d\n", ans);
    return 0;
}

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define mod 12345
#define maxc 1010
#define maxn 150
using namespace std;
typedef long long LL;
struct Matrix
{
    int digit[maxn][maxn],n,m;
    friend Matrix operator * (const Matrix &a,const Matrix &b)
    {
        static Matrix c;
        memset(c.digit,0,sizeof(c.digit));
        c.n=a.n,c.m=b.m;
        for(int i=0;i<c.n;i++)
            for(int j=0;j<c.m;j++)
                for(int k=0;k<a.m;k++)
                    c.digit[i][j]=(c.digit[i][j]+a.digit[i][k]*b.digit[k][j])%mod;
        return c;
    }
}square,ans;
LL m;
int n,c[maxc],seq[maxc];
vector<int> to[30];
int N,sum[maxc];
Matrix power(Matrix p,LL n)
{
    Matrix ans;
    ans.n=p.n,ans.m=p.m;
    for(int i=0;i<ans.n;i++)
        for(int j=0;j<ans.n;j++)
            ans.digit[i][j]=(i==j);
    for(;n;n>>=1,p=p*p)
        if(n&1)
            ans=ans*p;
    return ans;
}
void read()
{
    cin>>m>>n;
    char str[10];
    for(int i=1;i<=n;i++)
    {
        scanf("%s %d",str+1,&c[i]);
        to[str[1]-'A'+1].push_back(i);
        N*=c[i];
    }
    sum[n]=1;
    for(int i=n-1;i>=1;i--)
        sum[i]=sum[i+1]*c[i+1];
    N=sum[1]*c[1];
    square.n=N,square.m=N;
}
int hash()
{
    int total=0;
    for(int i=1;i<=n;i++)
        total=total+seq[i]*sum[i];
    return total;
}
void tran()
{
    int x=hash();
    for(int i=1;i<=26;i++)
        if(to[i].size())
        {
            for(int j=0;j<to[i].size();j++)
                seq[to[i][j]]=(seq[to[i][j]]+1)%c[to[i][j]];
            int y=hash();
            square.digit[x][y]++;
            for(int j=0;j<to[i].size();j++)
                seq[to[i][j]]=(seq[to[i][j]]-1+c[to[i][j]])%c[to[i][j]];
        }
}
void DFS(int p)
{
    if(p>n)
    {
        tran();
        return ;
    }
    for(int i=0;i<c[p];i++)
    {
        seq[p]=i;
        DFS(p+1);
    }
}
LL work()
{
    if(n==0&&m==0)
        return 1;
    ans.n=1,ans.m=N;
    ans.digit[0][0]=1;
    ans=ans*power(square,m);
    LL total=0;
    for(int i=0;i<N;i++)
    {
        int s=i,tot=0;
        for(int j=1;j<=n;j++)
        {
            seq[j]=s/sum[j];
            s%=sum[j];
        }
        for(int j=1;j<=26;j++)
        {
            if(to[j].size()==0)
                tot++;
            else
            {
                for(int k=0;k<to[j].size();k++)
                    if(seq[to[j][k]]==0)
                    {
                        tot++;
                        break;
                    }
            }
        }
        if(tot==26)
            total=(total+ans.digit[0][i])%mod;
    }
    return total;
}
int main()
{
    read();
    DFS(1);
    cout<<work()<<endl;
    return 0;
}

#include <bits/stdc++.h>

#define mp make_pair
#define pb push_back

using namespace std;

typedef long long ll;

const int N = 130;
const int md = 12345;

int f[N][N], g[N][N];
vector<int> v[26];
ll n;
int lcm[26];
int valid[N];
int tot;
int c[2][26];

void decode(int a, int c[26]){
	for(int i = 25; i >= 0; --i){
		if (v[i].size()) c[i] = a % lcm[i], a /= lcm[i];
		else c[i] = 1;
	}
}

int match(int a, int b){
	decode(a - 1, c[0]);
	decode(b - 1, c[1]);
	int fnd = 0, fre = 0;
	for(int i = 0; i < 26; ++i){
		if (v[i].size() == 0) continue;
		if ((c[0][i] + 1) % lcm[i] == c[1][i]){
			if (lcm[i] == 1) fre++;
			else if (!fnd) fnd = 1;
			else return 0;
		}
		else if (c[0][i] != c[1][i]) return 0;
	}
	if (fnd) return 1;
	return fre;
}

void mul(int a[N][N], int b[N][N]){
	int c[N][N];
	for(int i = 1; i <= tot; ++i){
		for(int j = 1; j <= tot; ++j){
			c[i][j] = 0;
			for(int k = 1; k <= tot; ++k){
				c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % md;
			}
		}
	}
	for(int i = 1; i <= tot; ++i){
		for(int j = 1; j <= tot; ++j){
			b[i][j] = c[i][j];
		}
	}
}

bool bad(int i, int j){
	for(int k = 0; k < v[j].size(); ++k){
		if (i % v[j][k] == 0) return false;
	}
	return true;
}

bool check(int c[26]){
	for(int i = 0; i < 26; ++i) if (v[i].size()){
		if (bad(c[i], i)) return false;
	}
	return true;
}

int main(){
//	freopen("input.inp", "r", stdin);
	int m;
	scanf("%I64d%d",&n,&m);
	for(int i = 0; i < 26; ++i) lcm[i] = 1;
	while (m--){
		char a[5];
		int x;
		scanf("%s%d",&a,&x);
		v[a[0] - 'A'].pb(x);
	}
	tot = 1;
	for(int i = 0; i < 26; ++i) if (v[i].size()){
		lcm[i] = v[i][0];
		for(int j = 1; j < v[i].size(); ++j)
			lcm[i] = lcm[i] * v[i][j] / __gcd(v[i][j], lcm[i]);
		tot *= lcm[i];
	}
	for(int i = 1; i <= tot; ++i){
		for(int j = 1; j <= tot; ++j){
			g[j][i] = match(i, j);
		}
	}
	mul(g, f);

	f[1][1] = 1;
	for(int i = 0; i < 64; ++i, mul(g, g))
		if (n & (1ll << i)) mul(g, f);
	int ans = 0;
	for(int i = 1; i <= tot; ++i){
		decode(i - 1, c[0]);
		if (check(c[0])){
			ans = (ans + f[i][1]) % md;
		}
	}
	printf("%d",ans);
	return 0;
}

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<set>
#include<vector>
#include<map>
#include<queue>
#include<string>
#include<bitset>
#include<iomanip>
#include<iostream>
#include<cmath>
using namespace std;
#define rep(i,x,y) for(i=x;i<=y;i++)
#define _rep(i,x,y) for(i=x;i>=y;i--)
#define REP(i,x,y) for(int i=(x);i<=(y);i++)
#define _REP(i,x,y) for(int i=(x);i>=(y);i--)
#define CL(S,x) memset(S,x,sizeof(S))
#define CP(S1,S2) memcpy(S1,S2,sizeof(S2))
#define ALL(x,S) for(x=S.begin();x!=S.end();x++)
#define pb push_back
#define IN insert
#define ER erase
#define BE begin()
#define ED end()
#define LB lower_bound
#define UB upper_bound
#define mp make_pair
#define fi first
#define se second
#define upmin(x,y) x=min(x,y)
#define upmax(x,y) x=max(x,y)
#define COUT(S,x) cout<<fixed<<setprecision(x)<<S<<endl
typedef long long ll;
typedef long double ld;
typedef pair<int,int> pii;
template<class T> inline void read(T&x){bool fu=0;char c;for(c=getchar();c<=32;c=getchar());if(c=='-')fu=1,c=getchar();for(x=0;c>32;c=getchar())x=x*10+c-'0';if(fu)x=-x;};
template<class T> inline void read(T&x,T&y){read(x);read(y);}
template<class T> inline void read(T&x,T&y,T&z){read(x);read(y);read(z);}
inline char getc(){char c;for(c=getchar();c<=32;c=getchar());return c;}
ll T;int n,m,i,j,k,l,p;
char c1[1100];int x[1100];
const int L=125;
const int mod=12345;
struct mat{int s[L][L];}G,E;
mat operator+(mat a,mat b){mat c;int i,j;rep(i,0,n)rep(j,0,n)c.s[i][j]=(a.s[i][j]+b.s[i][j])%mod;return c;}
mat operator*(mat a,mat b){mat c;int i,j,k;rep(i,0,n)rep(j,0,n){c.s[i][j]=0;rep(k,0,n)c.s[i][j]=(c.s[i][j]+1LL*a.s[i][k]*b.s[k][j])%mod;}return c;}
mat operator^(mat a,ll x){mat ans=E;for(;x;x>>=1,a=a*a)if(x&1)ans=ans*a;return ans;}
mat ten(mat a){mat t0=a*a;mat t1=t0*t0;t1=t1*t1;return t0*t1;}
void print(mat a){int i,j;rep(i,0,n)rep(j,0,n)printf("%d%s",a.s[i][j],j==n?"\n":" ");}
int a[1100],b[1100];bool vv[30],can[30];
int st[1100];
void dfs(int i)
{
    if(i>m)
    {
        CP(b,a);
        int d=0;for(int j=1;j<=m;j++)d=d*x[j]+b[j];
        E.s[d][d]=1;upmax(n,d);

        CL(can,0);for(int j=1;j<=m;j++)if(b[j]==0)can[c1[j]-'A']=1;
        bool pd=1;for(int k=0;k<=25;k++)if(vv[k]&&(!can[k])){pd=0;break;}
        if(pd)st[++st[0]]=d;

        for(int k=0;k<=25;k++)if(vv[k])
        {
            for(int j=1;j<=m;j++)b[j]=a[j];
            for(int j=1;j<=m;j++)if(c1[j]-'A'==k)b[j]=(b[j]+1)%x[j];
            int d2=0;for(int j=1;j<=m;j++)d2=d2*x[j]+b[j];
            //printf("%d %d\n",d,d2);
            G.s[d][d2]++;
        }
        return;
    }
    for(int j=0;j<x[i];j++)
    {
        a[i]=j;
        dfs(i+1);
    }

}
int main()
{
    #ifndef ONLINE_JUDGE
        freopen("a.in","r",stdin);freopen("a.out","w",stdout);
    #endif

    read(T);read(m);
    rep(i,1,m)c1[i]=getc(),vv[c1[i]-'A']=1,read(x[i]);

    dfs(1);

    G=G^T;

    int ans=0;
    rep(i,1,st[0])
    ans=(ans+G.s[0][st[i]])%mod;
    printf("%d\n",ans);

    scanf("\n");
    return 0;
}

#include <bits/stdc++.h>
//Damned if I don't take what I want.

using namespace std;

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

const int MAXM = 150, MAXA = 26, MOD = 12345;

inline int add(int a, int b){ return ( ll(a) + b ) % MOD; }
inline int mul(int a, int b){ return ( ll(a) * b ) % MOD; }

int trans[MAXM][MAXM], temp[MAXM][MAXM], fin[MAXM][MAXM], ans[MAXM];
vector<int> multip[MAXA];
int base[MAXA], pre[MAXA + 1];

int MSK;
inline void smul(int c[MAXM][MAXM], int a[MAXM][MAXM], int b[MAXM][MAXM]){
	memset(c, 0, sizeof temp);
	for (int i = 0; i < MSK; i++)
		for (int k = 0; k < MSK; k++)
			for (int j = 0; j < MSK; j++)
				c[i][j] = add(c[i][j], mul(a[i][k], b[k][j]));
}

int fact[MAXA];
void factorize(int x){
	for (int i = 0; i < MAXA; i++){
		fact[i] = x % base[i];
		x /= base[i];
	}
}

int toint(){
	int outp = 0;
	for (int i = 0; i < MAXA; i++)
		outp += fact[i] * pre[i];
	return outp;
}

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

	ll n; int c; cin >> n >> c;

	for (int i = 0; i < MAXA; i++)
		base[i] = 1;

	for (int i = 0; i < c; i++){
		char ch; int x; cin >> ch >> x;
		ch -= 'A';
		multip[ch].push_back(x);
		base[ch] *= x;
	}

	pre[0] = 1;
	for (int i = 0; i < MAXA; i++)
		pre[i + 1] = pre[i] * base[i];
	MSK = pre[MAXA];

	for (int i = 0; i < MSK; i++){
		factorize(i);
		for (int j = 0; j < MAXA; j++) if (multip[j].size()){
			fact[j] = (fact[j] -1 + base[j]) % base[j];
			trans[i][ toint() ]++;
			fact[j] = (fact[j] + 1) % base[j];
		}
	}

	/*cerr << "MSK : " << MSK << endl;
	for (int i = 0; i < MSK; i++, cerr << "\n")
		for (int j = 0; j < MSK; j++)
			cerr << trans[i][j] << " ";*/

	for (int i = 0; i < MSK; i++) fin[i][i] = 1;

	while(n){
		if (n % 2){
			memcpy(temp, fin, sizeof fin);
			smul(fin, trans, temp);
		}

		memcpy(temp, trans, sizeof trans);
		smul(trans, temp, temp);

		n /= 2;
	}

	int outp = 0;
	for (int i = 0; i < MSK; i++) {
		ans[i] = fin[i][0];
		factorize(i);

		bool ok = true;
		for (int j = 0; j < MAXA && ok; j++) if (multip[j].size()){
			bool found = false;
			for (int k = 0; k < multip[j].size() && !found; k++)
				if (fact[j] % multip[j][k] == 0) found = true;
			ok &= found;
		}

		if (ok) outp = add(outp, ans[i]);
	}

	cout << outp << endl;
}

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
const int MAXN = 1000;
const int MAXM = 123;
const int MOD = 12345;
int d_mul;
struct Matrix{
    int a[MAXM+5][MAXM+5];
    Matrix(int d=0){
        memset(a, 0, sizeof a);
        for(int i=1;i<=d_mul;i++)
            a[i][i] = d;
    }
    Matrix operator*(const Matrix& rhs)const{
        Matrix ret;
        for(int i=1;i<=d_mul;i++){
            for(int j=1;j<=d_mul;j++){
                for(int k=1;k<=d_mul;k++){
                    ret.a[i][j] += a[i][k]*rhs.a[k][j]%MOD;
                    ret.a[i][j] %= MOD;
                }
            }
        }
        return ret;
    }
};
Matrix mpow(Matrix a, long long b){
    Matrix ret(1);
    while(b){
        if(b&1)
            ret=ret*a;
        a=a*a;
        b>>=1;
    }
    return ret;
}
pair<char, int> lim[MAXN+10];
int c, idcnt;
map<vector<int>, int> id;
vector<int> rid[MAXM+10];
void dfs(int u, vector<int> cur){
    if(u > c){
        ++idcnt;
        id[cur] = idcnt;
        rid[idcnt] = cur;
        return ;
    }
    for(int j=0;j<lim[u].second;j++){
        vector<int> nex = cur;
        nex.push_back(j);
        dfs(u+1, nex);
    }
}
inline bool check(register int id){
    for(int i=1;i<=c;i++){
        int nex=i;
        while(nex<c && lim[nex+1].first == lim[i].first)
            nex ++;
        bool ok = false;
        for(int j=i;j<=nex && !ok;j++)
            if(rid[id][j-1] == 0)
                ok = true;
        if(!ok)
            return false;
        i = nex;
    }
    return true;
}
int main(){
    long long n;
    cin>>n>>c;
    char str[10];
    d_mul = 1;
    for(int i=1;i<=c;i++){
        scanf("%s", str);
        lim[i].first = str[0];
        scanf("%d", &lim[i].second);
        d_mul *= lim[i].second;
    }
    sort(lim+1, lim+1+c);
    vector<int> tmp;
    dfs(1, tmp);
    Matrix mat;
    for(map<vector<int>, int>::iterator iter=id.begin();iter!=id.end();iter++){
        for(int i=0;i<26;i++){
            vector<int> nexid = iter->first;
            bool has_lim = false;
            for(int j=1;j<=c;j++){
                if(lim[j].first == i+'A'){
                    nexid[j-1] = (nexid[j-1]+1)%lim[j].second;
                    has_lim = true;
                }
            }
            if(has_lim)
                mat.a[iter->second][id[nexid]] ++;
        }
    }
    mat = mpow(mat, n);
    int ans = 0;
    for(int i=1;i<=idcnt;i++){
        if(!mat.a[1][i])
            continue;
        if(check(i))
            ans = (ans+mat.a[1][i])%MOD;
    }
    printf("%d\n", ans);

    return 0;
}

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

typedef vector<vector<int> > Matrix;
typedef long long ll;

const int MOD = 12345;
int add(int a, int b) { return a+b-(a+b>=MOD)*MOD; }
int mult(int a, int b) { return (1LL*a*b)%MOD; }

Matrix make(int a, int b) { return Matrix(a,vector<int>(b)); }
Matrix mult(Matrix a, Matrix b) {
	Matrix res = make(a.size(),b[0].size());
	for (int i=0;i<a.size();i++) {
		for (int j=0;j<b[0].size();j++) {
			for (int k=0;k<a[0].size();k++) {
				res[i][j] = add(res[i][j],mult(a[i][k],b[k][j]));
			}
		}
	}
	return res;
}
Matrix modpow(Matrix x, ll p) {
	Matrix ans = make(x.size(),x.size());
	for (int i=0;i<x.size();i++) ans[i][i] = 1;
	while (p) {
		if (p&1) ans = mult(ans,x);
		p>>=1;
		x = mult(x,x);
	}
	return ans;
}

ll n,m;
set<int> conditions[27];
int lcmd[27];
int good[27][130];
int D = 0;
map<vector<int>,int> mp;
vector<int> states[125];

void getstates(vector<int> v, int cur){
	if(cur==26){
		states[D] = v;
		mp[v] = D;
		D++;
		//cout << v << endl;
		return;
	}
	for(int i=0;i<lcmd[cur];i++){
		v[cur]=i;
		getstates(v, cur+1);
	}
}

int main(){

	cin >> n >> m;
	for(int i=0;i<m;i++){
		char c;int x;
		cin >> c >> x;
		conditions[c-'A'].insert(x);
	}
	for(int i=0;i<26;i++)lcmd[i]=1;
	for(int i=0;i<26;i++)for(auto t:conditions[i])lcmd[i]*=t;
	for(int i=0;i<26;i++){
		good[i][0]=1;
		for(auto t:conditions[i]){
			int cur = t;
			for(int j=0;j<lcmd[i];j+=cur){
				good[i][j]=1;
			}
		}
	}
	vector<int> v(26);
	iota(v.begin(),v.end(),0);
	getstates(v, 0);
	Matrix A = make(D,D);
	for(int i=0;i<D;i++){
		vector<int> v = states[i];
		for(int j=0;j<26;j++)if(!conditions[j].empty()){
			int c = lcmd[j];
			v[j] = (v[j]+1)%c;
			A[i][mp[v]]++;
			v[j] = (v[j]-1+c)%c;
		}
	}

	A = modpow(A, n);
	int ans = 0;
	for(int i=0;i<D;i++){
		vector<int> v = states[i];
		bool flag = true;
		for(int j=0;j<26;j++)if(!good[j][v[j]])flag = false;
		if(flag){
			ans = add(ans, A[0][i]);
		}
	}
	cout << ans << endl;

	return 0;
}

#include <cstdio>
#include <vector>
#include <cstring>
#include <algorithm>
using namespace std;

class Matrix{
public:
    static const int MOD = 12345;
    typedef long long LL;
    int n,m;
    int value[128][128];
    Matrix():n(),m(){}
    Matrix(int c):n(c),m(c){
        memset(value,0,sizeof(value));
        while(c--) value[c][c]=1;
    }
    Matrix(int n, int m):n(n),m(m){
        memset(value,0,sizeof(value));
    }
    int* operator [](int r){return value[r];}
    const int* operator [](int r) const{return value[r];}
    struct SizeMismatch{};
    Matrix& operator *=(const Matrix& c){return *this=*this*c;}
    Matrix operator ~() const{
        Matrix ret(m,n);
        for(int i=0;i<m;i++) for(int j=0;j<n;j++) ret[i][j]=value[j][i];
        return ret;
    }
    Matrix operator *(const Matrix& c) const{
        if(m!=c.n) throw SizeMismatch();
        Matrix ret(n,c.m);
        for(int k=0;k<m;k++) for(int i=0;i<n;i++) for(int j=0;j<c.m;j++)
            ret[i][j]=(ret[i][j]+LL(value[i][k])*c[k][j])%MOD;
        return ret;
    }
    Matrix pow(long long e) const{
        if(n!=m) throw SizeMismatch();
        Matrix ret=n,c=*this;
        for(;e;e>>=1,c*=c) if(e&1) ret*=c;
        return ret;
    }
};

int encode(const vector<int>& u, const vector<int>& o){
    int ret=0;
    for(size_t i=o.size()-1;~i;i--){
        ret*=o[i];
        ret+=u[i]%o[i];
    }
    return ret;
}

vector<int> decode(int x, const vector<int>& o){
    vector<int> u;
    for(size_t i=0;i<o.size();i++){
        u.push_back(x%o[i]);
        x/=o[i];
    }
    return u;
}

bool check(const vector<int>& u, const vector<int> w[]){
    for(size_t i=0,j;i<u.size();i++){
        for(j=0;j<w[i].size();j++) if(u[i]%w[i][j]==0) break;
        if(j==w[i].size()) return false;
    }
    return true;
}

int main(){
    long long n;
    int c,ans=0,sz=1;
    scanf("%I64d%d",&n,&c);
    vector<int> w[26],o;
    for(int i=0;i<c;i++){
        char str[5];
        int now;
        scanf("%s%d",str,&now);
        w[*str-'A'].push_back(now);
    }
    for(int i=0;i<26;i++) if(w[i].size()){
        sort(w[i].begin(),w[i].end());
        w[i].erase(unique(w[i].begin(),w[i].end()),w[i].end());
        o.push_back(1);
        for(size_t j=0;j<w[i].size();j++)
            o.back()*=w[i][j]/__gcd(o.back(),w[i][j]);
        sz*=o.back();
        w[o.size()-1]=w[i];
    }
    Matrix a(sz,sz);
    for(int i=0;i<sz;i++){
        vector<int> u=decode(i,o);
        for(auto& x:u){
            x++;
            a[i][encode(u,o)]++;
            x--;
        }
    }
    a=a.pow(n);
    for(int i=0;i<sz;i++) if(check(decode(i,o),w)) ans+=a[0][i];
    printf("%d\n",ans%a.MOD);
}

#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
#include <string>
#include <iomanip>
#include <set>
#include <map>
#include <queue>
#include <bitset>
#include <random>
#include <chrono>
#include <numeric>
typedef long long ll;
typedef long double ld;
using namespace std;

const ll mod = 12345;
vector<vector<ll> > multiply(vector<vector<ll> >& a, vector<vector<ll> >& b)
{
	int n = a.size();
	vector<vector<ll> > res(n, vector<ll>(n, 0));
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			for (int k = 0; k < n; k++)
			{
				res[i][j] += (a[i][k] * b[k][j]) % mod;
				res[i][j] %= mod;
			}
		}
	}
	return res;
}
vector<vector<ll> > pwr(vector<vector<ll> > a, ll b)
{
	if (b == 1)
	{
		return a;
	}
	vector<vector<ll> > half = pwr(a, (b >> 1));
	half = multiply(half, half);
	if (b & 1)
	{
		half = multiply(half, a);
	}
	return half;
}
const int crimes = 26;
vector<set<int> > laws(crimes);
vector<ll> prod(crimes, 0);
int from_state_to_num(vector<ll> com)
{
	int ans = 0;
	for (int i = 0; i < crimes; i++)
	{
		if (prod[i])
		{
			ans *= prod[i];
			ans += com[i];
		}
	}
	return ans;
}
vector<ll> from_num_to_state(int num)
{
	vector<ll> ans(crimes, 0);
	for (int i = crimes - 1; i >= 0; i--)
	{
		if (prod[i])
		{
			ans[i] = num % prod[i];
			num /= prod[i];
		}
	}
	return ans;
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	ll n;
	int c;
	cin >> n >> c;
	if (!n)
	{
		cout << 1 << "\n";
		return 0;
	}
	ll p = 1;
	for (int i = 0; i < c; i++)
	{
		char crime;
		int how_many;
		cin >> crime >> how_many;
		laws[crime - 'A'].insert(how_many);
		if (!prod[crime - 'A'])
		{
			prod[crime - 'A'] = 1;
		}
		prod[crime - 'A'] *= how_many;
		p *= how_many;
	}
	vector<vector<ll> > m(p, vector<ll>(p, 0));
	for (int i = 0; i < p; i++)
	{
		vector<ll> old = from_num_to_state(i);
		for (int j = 0; j < crimes; j++)
		{
			if (!prod[j])
			{
				continue;
			}
			vector<ll>nw = old;
			nw[j] = (nw[j] + 1) % prod[j];
			m[i][from_state_to_num(nw)]++;
		}
	}
	m = pwr(m, n);
	ll ans = 0;
	for (int i = 0; i < p; i++)
	{
		vector<ll> old = from_num_to_state(i);
		bool good = true;
		for (int j = 0; j < crimes; j++)
		{
			if (laws[j].size())
			{
				bool now = false;
				for (int k : laws[j])
				{
					if (old[j] % k == 0)
					{
						now = true;
					}
				}
				good &= now;
			}
		}
		if (good)
		{
			ans += m[0][i];
			ans %= mod;
		}
	}
	cout << ans << "\n";
	return 0;
}

#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
using namespace std;
const int MODER=12345;
int gcd(int x,int y){
	return y?gcd(y,x%y):x;
}
int lcm(int x,int y){
	return x/gcd(x,y)*y;
}
int idGen;
struct Mat{
	int v[150][150];
	int* operator [](int id){
		return v[id];
	}
	friend Mat operator *(Mat& a,Mat &b){
		Mat c;
		memset(&c,0,sizeof(c));
		for(int i=0;i<idGen;i++)
			for(int j=0;j<idGen;j++)
				for(int k=0;k<idGen;k++)
					c[i][j]=(c[i][j]+a[i][k]*b[k][j])%MODER;
		return c;
	}
};

Mat mat;

map<vector<int>,int> m;
bool has[100];
bool ok[100][150];
bool fine[150];
int llcm[100];
int cnt;
long long n;
int make(const vector<int>& v){
	map<vector<int>,int>::iterator it=m.find(v);
	if(it!=m.end())return it->second;
	int id=idGen++;
	m.insert(make_pair(v,id));
	fine[id]=true;
	for(int i=0;i<26;i++)
		if(has[i])
			fine[id]=fine[id] && ok[i][v[i]];
	for(int i=0;i<26;i++)
		if(has[i]){
			vector<int> next(v);
			next[i]=(next[i]+1)%llcm[i];
			mat[id][make(next)]++;
		}
	return id;
}
int main(){
	scanf("%I64d%d",&n,&cnt);
	for(int i=1;i<=cnt;i++){
		char tmp[10];
		int x;
		scanf("%s%d",tmp,&x);
		ok[tmp[0]-'A'][x]=true;
		has[tmp[0]-'A']=true;
	}

	for(int i=0;i<26;i++){
		llcm[i]=1;
		for(int j=1;j<123;j++)if(ok[i][j]){
			llcm[i]=lcm(llcm[i],j);
		}
		//printf("llcm[%d]=%d\n",i,llcm[i]);
		for(int j=123-1;j;j--)if(ok[i][j])
			for(int k=j;k<123;k+=j)
				ok[i][k]=true;
		ok[i][0]=true;
	}

	make(vector<int>(26));
	Mat res;
	memset(&res,0,sizeof(res));
	for(int i=0;i<150;i++)
		res[i][i]=1;
	for(int i=63;i>=0;i--){
		res=res*res;
		if(n>>i&1)
			res=res*mat;
	}
	int ans=0;
	for(int i=0;i<idGen;i++)if(fine[i])
		ans=(ans+res[0][i])%MODER;
	cout<<ans<<endl;
}

/*
「God Is In His Heaven,
		All's Right With The World.」
*/
#define _CRT_SECURE_NO_WARNINGS
#include <bits/stdc++.h>
#define fi first
#define se second
#define mp make_pair
#define pb push_back
#define rep(i, a, b) for(int i=(a); i<(b); i++)
#define per(i, a, b) for(int i=(a)-1; i>=(b); i--)
#define each(i, q) for(auto& i : q)
#define sz(a) (int)a.size()
#define de(a) cout<<#a<<" = "<<a<<endl
#define dd(a) cout<<#a<<" = "<<a<<" "
#define lowbit(x) x&(-x)
#define all(x) x.begin(),x.end()
#define ffs __builtin_ffs //idxOf(1<-)
#define clz __builtin_clz //numOf(->0)
#define ctz __builtin_ctz //numOf(0<-)
#define popcount __builtin_popcount //numOf1
#define parity __builtin_parity //(numOf1)%2
using namespace std;
typedef long long ll;
typedef double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef vector<int> vi;
typedef vector<vi > vvi;
typedef vector<pii > vpii;
typedef vector<pll > vpll;
typedef vector<ll> vl;
typedef vector<vl > vvl;
template <typename T> inline void rd(T& x) { int f = 0, c = getchar(); x = 0; while (!isdigit(c)) f |= c == '-', c = getchar(); while (isdigit(c)) x = x * 10 + c - 48, c = getchar(); if (f) x = -x; }
template <typename T, typename... Args> inline void rd(T& x, Args& ... args) { rd(x); rd(args...); }
template <typename T> void we(T x) { if (x < 0) x = -x, putchar('-'); if (x > 9) we(x / 10); putchar(x % 10 + 48); }
template <typename T> void ws(T x) { we(x); putchar(' '); }
template <typename T> void wln(T x) { we(x); puts(""); }
template <typename T, typename... Args> inline void wln(const T& x, const Args& ... args) { ws(x); if (sizeof...(args) > 1) ws(args...); else wln(args...);}
template <typename T> inline bool cmin(T& x, const T& y) { return y < x ? (x = y, true) : false; }
template <typename T> inline bool cmax(T& x, const T& y) { return x < y ? (x = y, true) : false; }
const int maxn = (int)3e5 + 10;
const ll inf = (ll)1e18;
const ll mod = (ll)12345;
/*
	——ASUKA STRIKES!
*/
typedef vvl mat;
ll pw(ll a, ll b) {
	a %= mod;
	ll r = 1; for (; b; b >>= 1, a = a * a % mod) if (b & 1) r = r * a % mod;
	return r;
}
mat iden(int n) {
	mat r = mat(n, vl(n, 0));
	for (int i = 0; i < n; i++) r[i][i] = 1;
	return r;
}
mat mul(mat a, mat b, int m) {
	mat r = mat(sz(a), vl(sz(b[0]), 0));
	rep(i, 0, sz(a)) rep(j, 0, sz(b[0])) rep(k, 0, sz(a[0])) {
		r[i][j] += a[i][k] * b[k][j] % m;
		if (r[i][j] >= m) r[i][j] -= m;
	}
	return r;
}
mat pw(mat a, ll b, int m) {
	mat r = iden(sz(a));
	for (; b; b >>= 1, a = mul(a, a, m)) if (b & 1) r = mul(r, a, m);
	return r;
}
ll n, c, ans;
struct Elem {
	vi v;
	Elem() { v = vi(26, 0); }
	bool operator< (const Elem& e) const {
		rep(i, 0, 25) {
			if (v[i] == e.v[i]) continue;
			return v[i] < e.v[i];
		}
		return v[25] < e.v[25];
	}
};
map<Elem, int> maps;
vi v[26];
int pdt[1001];
int main() {
	rd(n, c);
	rep(i, 0, c) {
		char ch = getchar();
		int x; rd(x);
		if (!pdt[ch - 'A']) pdt[ch - 'A'] = x;
		else pdt[ch - 'A'] *= x;
		v[ch - 'A'].pb(x);
	}
	if (!n) return puts("1"), 0;
	if (!c) return puts("0"), 0;
	rep(iA, 0, pdt[0] ? pdt[0] : 1)
	rep(iB, 0, pdt[1] ? pdt[1] : 1)
	rep(iC, 0, pdt[2] ? pdt[2] : 1)
	rep(iD, 0, pdt[3] ? pdt[3] : 1)
	rep(iE, 0, pdt[4] ? pdt[4] : 1)
	rep(iF, 0, pdt[5] ? pdt[5] : 1)
	rep(iG, 0, pdt[6] ? pdt[6] : 1)
	rep(iH, 0, pdt[7] ? pdt[7] : 1)
	rep(iI, 0, pdt[8] ? pdt[8] : 1)
	rep(iJ, 0, pdt[9] ? pdt[9] : 1)
	rep(iK, 0, pdt[10] ? pdt[10] : 1)
	rep(iL, 0, pdt[11] ? pdt[11] : 1)
	rep(iM, 0, pdt[12] ? pdt[12] : 1)
	rep(iN, 0, pdt[13] ? pdt[13] : 1)
	rep(iO, 0, pdt[14] ? pdt[14] : 1)
	rep(iP, 0, pdt[15] ? pdt[15] : 1)
	rep(iQ, 0, pdt[16] ? pdt[16] : 1)
	rep(iR, 0, pdt[17] ? pdt[17] : 1)
	rep(iS, 0, pdt[18] ? pdt[18] : 1)
	rep(iT, 0, pdt[19] ? pdt[19] : 1)
	rep(iU, 0, pdt[20] ? pdt[20] : 1)
	rep(iV, 0, pdt[21] ? pdt[21] : 1)
	rep(iW, 0, pdt[22] ? pdt[22] : 1)
	rep(iX, 0, pdt[23] ? pdt[23] : 1)
	rep(iY, 0, pdt[24] ? pdt[24] : 1)
	rep(iZ, 0, pdt[25] ? pdt[25] : 1) {
		Elem now;
		now.v[0] = iA;
		now.v[1] = iB;
		now.v[2] = iC;
		now.v[3] = iD;
		now.v[4] = iE;
		now.v[5] = iF;
		now.v[6] = iG;
		now.v[7] = iH;
		now.v[8] = iI;
		now.v[9] = iJ;
		now.v[10] = iK;
		now.v[11] = iL;
		now.v[12] = iM;
		now.v[13] = iN;
		now.v[14] = iO;
		now.v[15] = iP;
		now.v[16] = iQ;
		now.v[17] = iR;
		now.v[18] = iS;
		now.v[19] = iT;
		now.v[20] = iU;
		now.v[21] = iV;
		now.v[22] = iW;
		now.v[23] = iX;
		now.v[24] = iY;
		now.v[25] = iZ;
		maps[now] = sz(maps);
	}
	mat m(sz(maps), vl(sz(maps), 0));
	each(i, maps) {
		rep(j, 0, 26) {
			if (pdt[j]) {
				Elem now = i.first;
				now.v[j] = (now.v[j] + 1) % pdt[j];
				m[i.second][maps[now]]++;
			}
		}
	}
	m = mul(m, pw(m, n - 1, mod), mod);
	each(i, maps) {
		Elem now = i.first;
		bool fail = 0;
		rep(j, 0, 26) {
			if (!pdt[j]) continue;
			bool fnd = 0;
			each(k, v[j]) {
				if (now.v[j] % k == 0) {
					fnd = 1;
					break;
				}
			}
			if (!fnd) {
				fail = 1;
				break;
			}
		}
		if (!fail) ans = (ans + m[0][i.second]) % mod;
	}
	wln(ans);
}

#include <stdio.h>
#include <sstream>
#include <iostream>
#include <fstream>
#include <algorithm>
#include <vector>
#include <set>
#include <map>
#include <stack>
#include <memory.h>
#include <queue>
#include <string>
#include <string.h>
#include <cmath>
#include <utility>
#include <time.h>

#define PI 3.1415926535897932384626433832795
#define sqr(x) ((x)*(x))
#define OUT_RT cerr << (float(clock()) / CLOCKS_PER_SEC) << endl

typedef long long LL;
typedef unsigned long long ULL;

using namespace std;

typedef int Tmatrix[125][125];

Tmatrix T, M, A;
int nn, m, c[1111], p[1111];
char t[1111];
LL n;

void Mul(Tmatrix& Res,const Tmatrix& A, const Tmatrix& B){
	for(int i=0;i<nn;i++)
		for(int j=0;j<nn;j++){
			int& sum = Res[i][j];
			sum = 0;
			for(int k=0;k<nn;k++)
				sum = (sum + A[i][k] * B[k][j]) % 12345;
		}
}

int main(){
//	freopen("input.txt","r",stdin);
//	freopen("output.txt","w",stdout);
	cin >> n >> m;
	nn = 1;
	for(int i=0;i<m;i++){
		cin >> t[i] >> p[i];
		c[i] = nn;
		nn *= p[i];
	}
	if(nn >= 125) throw 666;
	for(int i=0;i<nn;i++) {
		for(int ch=0;ch<26;ch++){
			int to = 0;
			bool any = false;
			for(int j=0;j<m;j++) if(t[j] == 'A' + ch){
				if( ((i / c[j]) % p[j]) != p[j] - 1 )
					to += ( ((i / c[j]) % p[j]) + 1 ) * c[j];
				any = true;
			}else to += ((i / c[j]) % p[j]) * c[j];
			if(any){
				M[i][to]++;
//				cout << i << " " << to << endl;
			}
		}
		A[i][i] = 1;
	}
	while(n){
		if(n&1){
			Mul(T, A, M);
			memcpy(A, T, sizeof(T));
		}
		n >>= 1;
		Mul(T, M, M);
		memcpy(M, T, sizeof(T));
	}

	int ans = 0;
	for(int i=0;i<nn;i++) {
		bool all = true;
		for(int ch=0;ch<26;ch++){
			bool any = false;
			bool good = false;
			for(int j=0;j<m;j++) if(t[j] == 'A' + ch){
				if(((i / c[j]) %p[j]) == 0){
					good = true;
					break;
				}
				any = true;
			}
			if(any && !good) {
				all = false;
				break;
			}
		}
		if(all) ans = (ans + A[i][0]) % 12345;
	}
	cout << ans << endl;
	return 0;
}

#include <cstdio>
#include <iostream>
#include <vector>
#include <memory.h>
#include <algorithm>
#include <map>

#define ll long long

using namespace std;

char type[1001];
int crat[1001],mod=12345,m;
vector < vector <int> > state;
vector <int> v;
bool need[27];

void gen(int t)
{
    if (t==m)
    {
        state.push_back(v);
        return;
    }
    for(int i=0;i<crat[t];i++)
    {
        v.push_back(i);
        gen(t+1);
        v.pop_back();
    }
}

int g[125][125],nx[125][27],tot;

vector <int> rec(ll n)
{
    if (n==0)
    {
        vector <int> ret(tot,0);
        ret[0]=1;
        return ret;
    }
    vector <int> v=rec(n>>1),ret(tot,0);
    for(int i=0;i<v.size();i++)
        for(int j=0;j<v.size();j++)
            ret[g[i][j]]=(ret[g[i][j]]+1LL*v[i]*v[j])%mod;
    if (n&1)
    {
        vector <int> tmp(tot),ret1(tot);
        for(int j=0;j<26;j++)
            if (need[j]) tmp[nx[0][j]]++;
        for(int i=0;i<ret.size();i++)
            for(int j=0;j<tmp.size();j++)
                ret1[g[i][j]]=(ret1[g[i][j]]+1LL*ret[i]*tmp[j])%mod;
        return ret1;
    }
    return ret;
}

int main()
{
//  freopen("input.txt","r",stdin);
//  freopen("output.txt","w",stdout);
    ll n;
    scanf("%I64d%d\n",&n,&m);
    for(int i=0;i<m;i++)
    {
        scanf("%c %d\n",&type[i],&crat[i]);
        need[type[i]-'A']=true;
    }
    bool leaf[1001]={0};
    for(int i=0;i<m;i++)
    {
        if (!leaf[i])
            for(int j=i+1;j<m;j++)
                if (type[j]==type[i]&&crat[j]==crat[i]) leaf[j]=true;
    }
    if (m)
    {
        int size=1;
        for(int i=1;i<m;i++)
            if (!leaf[i])
            {
                type[size]=type[i];
                crat[size]=crat[i];
                size++;
            }
        m=size;
    }
    gen(0);
//  for(int i=0;i<state.size();i++)
//  {
//      for(int j=0;j<state[i].size();j++)
//          cout << state[i][j] << "    ";
//      cout << endl;
//  }
//  for(int i=0;i<state.size();i++)
//      f[state[i]]=i;
//  vector <int> nv(state[0].size(),0);
    int mn[1002];
    mn[m]=1;
    mn[m-1]=crat[m-1];
    for(int i=m-2;i>=0;i--)
        mn[i]=mn[i+1]*crat[i];
    for(int i=0;i<state.size();i++)
    {
        for(int j=0;j<state.size();j++)
        {
            int num=0;
            for(int t=0;t<m;t++)
                num+=((state[i][t]+state[j][t])%crat[t])*mn[t+1];
            g[i][j]=num;
//          cout << i << "  " << j << " " << num << endl;
        }
    }
    for(int i=0;i<state.size();i++)
    {
        for(int j=0;j<26;j++)
        {
            if (!need[j]) continue;
            int num=0;
            for(int t=0;t<m;t++)
                num+=((state[i][t]+(type[t]==('A'+j)))%crat[t])*mn[t+1];
            nx[i][j]=num;
//          cout << i << "  " << j << " " << num << endl;
        }
    }
    tot=state.size();
    vector <int> v=rec(n);
//  for(int i=0;i<v.size();i++)
//      cout << v[i] << "   ";
//  cout << endl;
    int ans=0;
    for(int i=0;i<state.size();i++)
    {
        bool ok[27]={0};
        for(int j=0;j<state[i].size();j++)
            if (state[i][j]==0) ok[type[j]-'A']=true;
        bool add=true;
        for(int j=0;j<26;j++)
            if (need[j]&&!ok[j]) add=false;
        if (add) ans=(ans+v[i])%mod;
    }
    cout << ans << endl;
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

typedef long long int64;
const int mod = 12345;

struct Matrix
{
  int a[123][123];

  Matrix operator+(const Matrix &kj)
  {
    Matrix ret;
    for(int i = 0; i < 2; i++) {
      for(int j = 0; j < 2; j++) {
        ret.a[i][j] = a[i][j] + kj.a[i][j];
        ret.a[i][j] %= mod;
      }
    }
    return (ret);
  }

  Matrix operator*(const Matrix &kj)
  {
    Matrix ret = Matrix::Zero();
    for(int i = 0; i < 123; i++) {
      for(int j = 0; j < 123; j++) {
        for(int k = 0; k < 123; k++) {
          ret.a[i][j] = (ret.a[i][j] + 1LL * a[i][k] * kj.a[k][j]) % mod;
        }
      }
    }
    return (ret);
  }

  Matrix operator^(int64 n)
  {
    Matrix ret = Matrix::I();
    Matrix x = *this;
    while(n > 0) {
      if(n & 1LL) (ret = ret * x);
      x = x * x;
      n >>= 1LL;
    }
    return (ret);
  }

  static Matrix Zero()
  {
    Matrix ret;
    memset(ret.a, 0, sizeof(ret.a));
    return (ret);
  }

  static Matrix I()
  {
    Matrix ret;
    memset(ret.a, 0, sizeof(ret.a));
    for(int i = 0; i < 123; i++) ret.a[i][i] = 1;
    return (ret);
  }
};

int64 N;
int C;
vector< int > beet[26];
int lcm[26], all = 1;
vector< int > nums;

bool LatteMalta(int i)
{
  vector< int > t(26);
  int curr = i;
  for(int j : nums) {
    if(lcm[j] > 0) {
      t[j] = curr % lcm[j];
      curr /= lcm[j];
    }
  }
  for(int j : nums) {
    bool flag = false;
    for(int k : beet[j]) if(t[j] % k == 0) flag = 1;
    if(!flag) return (false);

  }
  return (true);
}

int main()
{
  cin >> N >> C;

  for(int i = 0; i < C; i++) {
    char T;
    int K;
    cin >> T >> K;
    beet[T - 'A'].push_back(K);
  }

  for(int i = 0; i < 26; i++) {
    if(!beet[i].empty()) nums.push_back(i);
  }

  for(int i : nums) {
    lcm[i] = 1;
    for(int j : beet[i]) lcm[i] = lcm[i] / __gcd(lcm[i], j) * j;
    all *= lcm[i];
  }

  Matrix mat = Matrix::Zero();

  for(int i = 0; i < all; i++) {
    vector< int > t(26);
    int curr = i;
    for(int j : nums) {
      t[j] = curr % lcm[j];
      curr /= lcm[j];
    }
    for(int j : nums) {
      t[j] = (t[j] + 1) % lcm[j];
      int val = 0;
      for(int k = 25; k >= 0; k--) {
        if(lcm[k] > 0) val = val * lcm[k] + t[k];
      }
      ++mat.a[i][val];
      t[j] = (t[j] + lcm[j] - 1) % lcm[j];
    }
  }

  mat = mat ^ N;
  int ret = 0;
  for(int i = 0; i < all; i++) {
    if(LatteMalta(i)) ret += mat.a[i][0];
  }
  cout << ret % mod << endl;
}

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

const int mod = 12345;

struct node
{
    char str[5];
    int x;
    bool operator <(const node &b)const
    {
        return x>b.x;
    }
}a[1010];

int num[30];

bool vis[1010][125];

int g[130][130],tmp[130][130],ans[130][130];

int now[1010];

int tot,m;

void power(long long y)
{
    int i,j,k;
    memset(ans,0,sizeof(ans));
    for(i=0;i<tot;i++)
        ans[i][i]=1;
    while(y)
    {
        if(y&1)
        {
            memset(tmp,0,sizeof(tmp));
            for(i=0;i<tot;i++)
                for(j=0;j<tot;j++)
                    for(k=0;k<tot;k++)
                        tmp[i][j]=(tmp[i][j]+ans[i][k]*g[k][j])%mod;
            for(i=0;i<tot;i++)
                for(j=0;j<tot;j++)
                    ans[i][j]=tmp[i][j];
        }
        memset(tmp,0,sizeof(tmp));
        for(i=0;i<tot;i++)
            for(j=0;j<tot;j++)
                for(k=0;k<tot;k++)
                    tmp[i][j]=(tmp[i][j]+g[i][k]*g[k][j])%mod;
        for(i=0;i<tot;i++)
            for(j=0;j<tot;j++)
                g[i][j]=tmp[i][j];
        y/=2;
    }
    return;
}

bool check(int y)
{
    int temp=y,i,j,flag;
    for(i=0;i<m;i++)
    {
        now[i]=temp%a[i].x;
        temp/=a[i].x;
    }
    for(i=0;i<26;i++)
    {
        flag=0;
        if(num[i]==0)
            continue;
        for(j=0;j<m;j++)
        {
            if((a[j].str[0]-'A'==i)&&(now[j]==0))
            {
                flag=1;
                break;
            }
        }
        if(flag==0)
            return false;
    }
    return true;
}

int main()
{
    int i,j,temp,k;
    tot=1;
    long long n;
    scanf("%I64d%d",&n,&m);
  //  printf("%I64d\n",n);
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    for(i=0,j=0;i<m;i++,j++)
    {
        scanf("%s%d",a[j].str,&a[j].x);
        if(vis[a[j].str[0]-'A'][a[j].x]==1)
        {
            j--;
            continue;
        }
        vis[a[j].str[0]-'A'][a[j].x]=1;
        num[a[j].str[0]-'A']++;
        tot=tot*a[j].x;
    }
    m=j;
    //printf("%d\n",j);
   // printf("%d\n",m);
    sort(a,a+m);
    int fuck=0;
    for(i=m-1;i>=0;i--)
    {
        if(a[i].x==1)
        {
            if(num[a[i].str[0]-'A']==1)
                fuck++;
        }
    }
    memset(g,0,sizeof(g));
    for(i=0;i<tot;i++)
    {
      //  printf("%d %d\n",i,tot);
        temp=i;
        for(j=0;j<m;j++)
        {
            now[j]=temp%a[j].x;
            temp/=a[j].x;
       //     printf("fuck %d %d %d\n",i,j,now[j]);
        }
        for(j=0;j<26;j++)
        {
            if(num[j]==0)
                continue;
            for(k=0;k<m;k++)
            {
                if(a[k].str[0]-'A'==j)
                    now[k]=(now[k]+1)%a[k].x;
            }
            temp=0;
            for(k=m-1;k>=0;k--)
            {
                temp=temp*a[k].x;
                temp=temp+now[k];
            }
            g[temp][i]=1;
            for(k=0;k<m;k++)
            {
                if(a[k].str[0]-'A'==j)
                    now[k]=(now[k]-1+a[k].x)%a[k].x;
            }
        }
        g[i][i]=fuck;
    }
/*
    for(i=0;i<tot;i++)
    {
        for(j=0;j<tot;j++)
            printf("%d ",g[i][j]);
        printf("\n");
    }
*/
    power(n);
/*
    for(i=0;i<tot;i++)
    {
        for(j=0;j<tot;j++)
            printf("%d ",ans[i][j]);
        printf("\n");
    }
*/
    int final=0;
    for(i=0;i<tot;i++)
    {
        if(check(i))
            final=(final+ans[0][i])%mod;
    }
    printf("%d\n",final);
    return 0;
}

#include<cstdio>
#include<cstring>
#include<iostream>

#define nn 210
#define mm 1010
#define Mod 12345
using namespace std;

char c[mm];
int h[nn],ck[nn],d[mm];long long l;
int st[nn],p[mm],tr[nn][nn],rs[nn][nn],n,m,N,ans;

inline void Get_arr(int a){
	for (int i=m;i>=1;i--) st[i]=a/p[i],a%=p[i];
}
inline int Get_id(int *a){
	int rs=0;
	for (int i=1;i<=m;i++) rs+=a[i]*p[i];
	return(rs);
}
inline void Get_tran(){
	p[1]=1;
	for (int i=2;i<=m;i++) p[i]=p[i-1]*d[i-1];
	N=p[m]*d[m];

	for (int i=0;i<N;i++){
		for (int j=0;j<26;j++) if(h[j]){
			Get_arr(i);
			for (int k=1;k<=m;k++) if(c[k]-'A'==j) st[k]=(st[k]+1)%d[k];
			tr[i][Get_id(st)]++;
		}
	}
}

int a[nn],b[nn][nn];
inline void Pow(){
	for (int i=0;i<N;i++) rs[i][i]=1;
	while (l){
		if (l&1){
			for (int i=0;i<N;i++)
			for (int j=0;j<N;j++) b[i][j]=rs[i][j],rs[i][j]=0;
			for (int k=0;k<N;k++)
			for (int i=0;i<N;i++)
			for (int j=0;j<N;j++) rs[i][j]=(rs[i][j]+b[i][k]*tr[k][j]%Mod)%Mod;
		}
		for (int i=0;i<N;i++)
		for (int j=0;j<N;j++) b[i][j]=tr[i][j],tr[i][j]=0;
		for (int k=0;k<N;k++)
		for (int i=0;i<N;i++)
		for (int j=0;j<N;j++) tr[i][j]=(tr[i][j]+b[i][k]*b[k][j]%Mod)%Mod;
		l/=2ll;
	}
}

int main()
{
	scanf("%I64d%d",&l,&m);
	if (!l) {puts("1");return(0);}
	for (int i=1;i<=m;i++){
		c[i]=getchar();
		while ('A'>c[i]||c[i]>'Z') c[i]=getchar();
		scanf("%d",&d[i]);h[c[i]-'A']=1;
	}

	Get_tran();
	Pow();

	for (int i=0;i<N;i++){
		Get_arr(i);
		bool jd=1;
		memset(ck,0,sizeof(ck));
		for (int j=1;j<=m;j++) if(!st[j]) ck[c[j]-'A']=1;
		for (int j=0;j<26;j++) if(h[j]&&!ck[j]) jd=0;
		if (jd) ans=(ans+rs[0][i])%Mod;
	}
	printf("%d\n",ans);
}

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

struct matrix
{int a[130][130];
};
struct matrix g,f,e;

struct unit
{int x;
 vector<int> w;
};
struct unit a[30];

long long n;
int m,ans;
int b[30],c[30];
const int mod=12345;

bool cmp(struct unit aa,struct unit bb)
{return aa.x>bb.x;
}

int gcd(int i,int j)
{if(j==0)
    return i;
 else
    return gcd(j,i%j);
}

matrix operator *(matrix aa,matrix bb)
{matrix ret;
 int i,j,k;
 memset(ret.a,0,sizeof(ret.a));
 for(i=0;i<=123;i++)
    for(k=0;k<=123;k++)
        if(aa.a[i][k])
        {   for(j=0;j<=123;j++)
                ret.a[i][j]=(ret.a[i][j]+aa.a[i][k]*bb.a[k][j]%mod)%mod;
        }
 return ret;
}

matrix fpow(long long j)
{matrix ret=e,t;
 t=g;
 while(j>0)
 {  if(j&1) ret=ret*t;
    t=t*t;
    j/=2;
 }
 return ret;
}

int main()
{int i,j,x,s,s1,flag;
 char ch[2];
 for(i=0;i<=123;i++)
    e.a[i][i]=1;
 scanf("%I64d%d",&n,&m);
 for(i=1;i<=m;i++)
 {  scanf("%s%d",ch,&x);
    if(a[ch[0]-64].x==0)
        a[ch[0]-64].x=x;
    else
        a[ch[0]-64].x=a[ch[0]-64].x*x/gcd(a[ch[0]-64].x,x);
    a[ch[0]-64].w.push_back(x);
 }
 sort(a+1,a+26+1,cmp);
 for(i=1;i<=26;i++)
    if(a[i].x==0)
    {   m=i-1;
        break;
    }
 for(i=m;i>=1;i--)
 {  b[i]=1;
    for(j=i+1;j<=m;j++)
        b[i]+=(a[j].x-1)*b[j];
 }
 while(c[0]==0)
 {  s=0;
    for(i=1;i<=m;i++)
        s+=c[i]*b[i];
    for(i=1;i<=m;i++)
    {   if(c[i]==a[i].x-1)
            s1=s-b[i]*(a[i].x-1);
        else
            s1=s+b[i];
        g.a[s][s1]++;
    }
    i=m;
    while(c[i]==a[i].x-1)
    {   c[i]=0;
        i--;
    }
    c[i]++;
 }
 /*
 for(i=0;i<=10;i++)
 {  for(j=0;j<=10;j++)
        cout<<g.a[i][j]<<" ";
    cout<<endl;
 }
 */
 f=fpow(n);
 memset(c,0,sizeof(c));
 while(c[0]==0)
 {  s=0;
    flag=1;
    for(i=1;i<=m;i++)
        s+=c[i]*b[i];
    for(i=1;i<=m;i++)
    {   flag=0;
        for(j=0;j<a[i].w.size();j++)
            if(c[i]%a[i].w[j]==0)
            {   flag=1;
                break;
            }
        if(!flag) break;
    }
    if(flag) ans=(ans+f.a[0][s])%mod;
    i=m;
    while(c[i]==a[i].x-1)
    {   c[i]=0;
        i--;
    }
    c[i]++;
 }
 cout<<ans<<endl;
 return 0;
}

#include <array>
#include <cstring>
#include <iostream>
#include <map>
#include <queue>
using namespace std;
namespace fio {
streambuf* in = cin.rdbuf();
char bb[1000000], *s = bb, *t = bb;
#define gc() \
  (s == t && (t = (s = bb) + in->sgetn(bb, 1000000), s == t) ? EOF : *s++)
inline long long read() {
  long long x = 0;
  char ch = gc();
  while (ch < 48) ch = gc();
  while (ch >= 48) x = x * 10 + ch - 48, ch = gc();
  return x;
}
}  // namespace fio
using fio::read;
long long n;
int m, llm;
int lim[26];
vector<int> road[26];
map<array<int, 26>, int> huaji;
array<int, 26> pm;
class mat {
 public:
  int val[125][125];
  int* operator[](int x) { return val[x]; }
  mat operator*(mat _) {
    mat ans;
    for (int i = 1; i <= llm; i++)
      for (int u = 1; u <= llm; u++) {
        ans[i][u] = 0;
        for (int j = 1; j <= llm; j++)
          ans[i][u] = (ans[i][u] + val[i][j] * _[j][u]) % 12345;
      }
    return ans;
  }
};
mat ksm(mat x, long long y) {
  mat ans = x;
  y--;
  for (; y; y >>= 1, x = x * x)
    if (y & 1) ans = ans * x;
  return ans;
}
mat base;
int ans;
int main() {
  n = read(), m = read();
  if (!n) return cout << 1, 0;
  if (!m) return cout << 0, 0;
  for (int i = 1, x, y; i <= m; i++)
    x = read() + '0' - 'A', road[x].emplace_back(y = read()),
    lim[x] = max(lim[x], 1) * road[x].back();
  while (pm[25] < max(lim[25], 1)) {
    huaji[pm] = ++llm, pm[0]++;
    for (int i = 0; i < 25; i++)
      if (lim[i])
        pm[i + 1] += pm[i] / lim[i], pm[i] %= lim[i];
      else
        pm[i + 1] += pm[i], pm[i] = 0;
  }
  for (pair<array<int, 26>, int> it : huaji)
    for (int i = 0; i < 26; i++)
      if (lim[i])
        it.first[i] = (it.first[i] + 1) % lim[i],
        base[it.second][huaji[it.first]]++,
        it.first[i] = (it.first[i] - 1 + lim[i]) % lim[i];
  base = ksm(base, n);
  for (pair<array<int, 26>, int> it : huaji) {
    bool flag = 1;
    for (int i = 0, fx = 0; flag && i < 26; i++, flag &= fx, fx = 0)
      if (!lim[i])
        fx = 1;
      else
        for (int p : road[i]) fx |= !(it.first[i] % p);
    flag ? ans = (ans + base[1][it.second]) % 12345 : ans;
  }
  cout << ans << endl;
}

#include<cstdio>
#include<iostream>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
typedef __int64 LL;
const int mod=12345;
const int N=130;
vector<int> ve[30];
#define pb push_back
int top,ww[N],sta[N];
int ll[30],rr[30];

void cp(int A[N][N],int B[N][N],int n){
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            A[i][j]=B[i][j];
        }
    }
}

int D[N][N];
void _mul(int A[N][N],int B[N][N],int n){
    memset(D,0,sizeof(D));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<n;k++){
                D[i][j]+=A[i][k]*B[k][j]%mod;
                D[i][j]%=mod;
            }
        }
    }
    cp(A,D,n);
}

int C[N][N];
void _pow(int A[N][N],LL b,int n){
    memset(C,0,sizeof(C));
    for(int i=0;i<n;i++){
        C[i][i]=1;
    }
    while(b){
        if(b&1){
            _mul(C,A,n);
        }
        _mul(A,A,n);
        b/=2;
    }
    cp(A,C,n);
}

void fco(int aa[N],int i){
    for(int j=top-1;j>=0;j--){
        aa[j]=i/ww[j];
        i%=ww[j];
    }
}

int A[N][N],B[N][N];
int aa[N];
void getA(int co){
    memset(A,0,sizeof(A));
    for(int i=0;i<co;i++){
        for(int j=0;j<26;j++)if(ve[j].size()){
            if(ve[j][0]==1){
                A[i][i]++;
            }
            else {
                fco(aa,i);

                for(int jj=ll[j];jj<=rr[j];jj++){
                    aa[jj]++;aa[jj]%=sta[jj];
                }

                int ii=0;
                for(int jj=0;jj<top;jj++){
                    ii+=aa[jj]*ww[jj];
                }
                A[ii][i]++;
            }
        }
    }
}

void getB(){
    memset(B,0,sizeof(B));
    for(int i=0;i<26;i++)if(ve[i].size()){
        if(ve[i][0]==1){
            B[0][0]++;
        }
        else {
            int ans=0;
            for(int j=ll[i];j<=rr[i];j++){
                ans+=ww[j];
            }
            B[ans][0]++;
        }
    }
}

int geta(int co){
    int ans=0;
    for(int i=0;i<co;i++){
        fco(aa,i);
        int fg=1;
        for(int j=0;j<26;j++)if(ve[j].size()&&ve[j][0]!=1){
            int flag=0;
            for(int jj=ll[j];jj<=rr[j];jj++){
                if(aa[jj]==0){
                    flag=1;break;
                }
            }
            fg=flag;
            if(!fg)break;
        }
        if(fg){
            ans+=A[i][0];ans%=mod;
        }
    }
    return ans;
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi
    LL n;int c;
    while(scanf("%I64d%d",&n,&c)!=EOF){
        for(int i=0;i<26;i++){
            ve[i].clear();
        }
        for(int i=0;i<c;i++){
            char ss[2];int a;
            scanf("%s%d",ss,&a);
            ve[ss[0]-'A'].pb(a);
        }
        if(n==0){
            printf("1\n");continue;
        }

        for(int i=0;i<26;i++){
            sort(ve[i].begin(),ve[i].end());
            ve[i].erase(unique(ve[i].begin(),ve[i].end()),ve[i].end());
            //printf("%d\n",ve[i].size());
        }

        int co=1;
        top=0;
        for(int i=0;i<26;i++)if(ve[i].size()&&ve[i][0]!=1){
            ll[i]=top;
            for(int j=0;j<ve[i].size();j++){
                sta[top]=ve[i][j];
                ww[top]=co;
                co*=ve[i][j];
                top++;
            }
            rr[i]=top-1;
        }

        getA(co);
        _pow(A,n-1,co);
        getB();
        _mul(A,B,co);
        printf("%d\n",geta(co));
    }
    return 0;
}

// Believe in yourself...
#include<bits/stdc++.h>
#define MP make_pair
#define PB push_back
#define PF push_front
#define POB pop_back
#define POF pop_front
#define F first
#define S second
#define sz(c) (c).size()
#define REP(i,n)  for(ll i=0;i<n;i++)
#define REPD(i,n) for(ll i=n-1;i>=0;i--)
#define FOR(i,a,b) for(ll i=a;i<=b;i++)
#define FORD(i,a,b) for(ll i=a;i>=b;i--)

#define bit(num,i) ((num>>i)&1)

using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<ll,ll> pll;
typedef vector<vector<ll> > matrice;

const ll alpha=27;
const ll mod=12345;

#pragma GCC Optimize("Ofast")

vector<ll>v[alpha];
ll lc[alpha];
bool vis[alpha];
ll tot=1;
ll cnt[alpha];

void build_sq(matrice &mat,ll num){
	mat.resize(num);
	REP(i,num)
		mat[i].resize(num);
}

matrice operator*(matrice a,matrice b){
	matrice c;
	c.resize(sz(a));
	REP(i,sz(a))
		c[i].resize(sz(b));
	REP(i,sz(a)){
		REP(j,sz(b)){
			REP(k,sz(a[0])){
				c[i][j]=(c[i][j]+(a[i][k]*b[k][j]))%mod;
			}
		}
	}
	return c;
}

matrice Pow(matrice a,ll b){
	matrice ans;
	build_sq(ans,sz(a));
	REP(i,sz(a))
		ans[i][i]=1;
	while(b>0){
		if(b%2)
			ans=ans*a;
		a=a*a;
		b/=2;
	}
	return ans;
}

void decode(ll num){
	REP(i,alpha){
		if(!vis[i])continue;
		cnt[i]=num%lc[i];
		num/=lc[i];
	}
}
ll code(){
	ll num=0;
	REPD(i,alpha){
		if(!vis[i])continue;
		num*=lc[i];
		num+=cnt[i];
	}
	return num;
}

matrice build_transition(){
	matrice mat;
	build_sq(mat,tot);
	REP(codes,tot){
		decode(codes);
		REP(i,alpha){
			if(!vis[i])continue;
			cnt[i]=(cnt[i]-1+lc[i])%lc[i];
			mat[codes][code()]++;
			cnt[i]=(cnt[i]+1)%lc[i];
		}
	}
	return mat;
}
matrice build_begin(){
	matrice mat;
	mat.resize(1);
	mat[0].resize(tot);
	REP(i,tot){
		decode(i);
		bool yes=1;
		REP(j,alpha)
			yes&=(cnt[j]==0);
		mat[0][i]=yes;
	}
	return mat;
}

void print(matrice mat){
	REP(i,sz(mat)){
		REP(j,sz(mat[0]))
			cout<<mat[i][j]<<" ";
		cout<<endl;
	}
}
int main(){
	ll n,c;cin>>n>>c;
	REP(i,c){
		char ch;
		ll a,b;
		cin>>ch>>b;
		a=ch-'A';
		if(!vis[a]){
			vis[a]=1;
			lc[a]=1;
		}
		v[a].PB(b);
		lc[a]*=b;
		tot*=b;
	}
	matrice mat=build_begin()*Pow(build_transition(),n);
	ll ans=0;
	REP(i,tot){
		decode(i);
		bool final_yes=1;
		REP(j,alpha){
			if(!vis[j])continue;
			bool yes=0;
			REP(k,sz(v[j]))
				yes|=(cnt[j]%v[j][k]==0);
			if(!yes){
				final_yes=0;
				break;
			}
		}
		if(final_yes)
			ans=(ans+mat[0][i])%mod;
	}
	cout<<ans;
}

#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

typedef long long ll;

struct para
{
    char l;
    int m;
};

const int MOD = 12345;
ll n, c;
vector< vector<int> > reszty;

bool Jest(vector<para>& a, int x, int y)
{
    for (int i = 0; i < a.size(); ++i)
        if (a[i].l == x && a[i].m == y)
            return true;
    return false;
}

bool por(para a, para b)
{
    if (a.l < b.l)
        return true;
    if (a.l > b.l)
        return false;
    return (a.m < b.m);
}

void gen(vector<int>& a, int nr, int x, vector<int>& ogr)
{
    a[nr] = x;
    if (nr == ogr.size() - 1)
    {
        reszty.push_back(a);
        return;
    }
    for (int i = 0; i < ogr[nr + 1]; ++i)
        gen(a, nr + 1, i, ogr);
}

vector< vector<int> > Mnoz(vector< vector<int> > a, vector< vector<int> > b)
{
    int n = a.size();
    vector< vector<int> > c(n, vector<int>(n, 0));
    for (int i = 0; i < n; ++i)
        for (int j = 0; j < n; ++j)
            for (int k = 0; k < n; ++k)
                c[i][j] = (c[i][j] + a[i][k] * b[k][j]) % MOD;
    return c;
}

vector< vector<int> > PotMat(vector< vector<int> > p, ll w)
{
    int n = p.size();
    if (w == 0)
    {
        vector< vector<int> > id(n, vector<int>(n, 0));
        for (int i = 0; i < n; ++i)
            id[i][i] = 1;
        return id;
    }
    if (w % 2 == 0)
    {
        vector< vector<int> > pol = PotMat(p, w / 2);
        return Mnoz(pol, pol);
    }
    return Mnoz(PotMat(p, w - 1), p);
}

int main()
{
    ios_base::sync_with_stdio(0);
    cin >> n >> c;
    if (n == 0)
    {
        cout << "1";
        return 0;
    }
    if (c == 0)
    {
        cout << "0";
        return 0;
    }
    vector<para> a;
    for (int i = 0; i < c; ++i)
    {
        char l;
        int m;
        cin >> l >> m;
        if (!Jest(a, l, m))
            a.push_back({l, m});
    }
    sort(a.begin(), a.end(), por);
    for (int l = 0; l < a.size(); )
    {
        int p = l;
        while (p < a.size() && a[p].l == a[l].l)
            ++p;
        --p;
        if (l == 0)
        {
            for (int i = l; i <= p; ++i)
                a[i].l = 'A';
        }
        else
        {
            for (int i = l; i <= p; ++i)
                a[i].l = a[l - 1].l + 1;
        }
        l = p + 1;
    }
    int ileLit = a.back().l - 'A' + 1;
    vector<int> mody(ileLit, 1);
    for (int i = 0; i < a.size(); ++i)
        mody[a[i].l - 'A'] *= a[i].m;
    vector<int> t(ileLit);
    for (int i = 0; i < mody[0]; ++i)
        gen(t, 0, i, mody);
    int ileReszt = reszty.size();
    vector< vector<int> > M(ileReszt, vector<int>(ileReszt, 0));
    for (int i = 0; i < ileReszt; ++i)
    {
        for (int j = 0; j < ileReszt; ++j)
        {
            int ilR = 0, nrR;
            for (int k = 0; k < ileLit; ++k)
            {
                if (reszty[i][k] != reszty[j][k])
                {
                    ++ilR;
                    nrR = k;
                }
            }
            if (ilR == 0)
            {
                for (int k = 0; k < ileLit; ++k)
                    if (mody[k] == 1)
                        ++M[j][i];
            }
            if (ilR == 1 && (reszty[i][nrR] + 1) % mody[nrR] == reszty[j][nrR])
                M[j][i] = (M[j][i] + 1) % MOD;
        }
    }
    M = PotMat(M, n - 1);
    vector<int> wek(ileReszt, 0);
    for (int i = 0; i < ileReszt; ++i)
    {
        int s = 0;
        for (int j = 0; j < ileLit; ++j)
            s += reszty[i][j];
        if (s == 0)
        {
            for (int j = 0; j < ileLit; ++j)
                if (mody[j] == 1)
                    ++wek[i];
        }
        if (s == 1)
            wek[i] = 1;
    }
    vector<int> wek2(ileReszt, 0);
    for (int i = 0; i < ileReszt; ++i)
        for (int j = 0; j < ileReszt; ++j)
            wek2[i] = (wek2[i] + M[i][j] * wek[j]) % MOD;
    int odp = 0;
    for (int i = 0; i < ileReszt; ++i)
    {
        vector<bool> ok(ileLit, false);
        for (int j = 0; j < a.size(); ++j)
            if (reszty[i][a[j].l - 'A'] % a[j].m == 0)
                ok[a[j].l - 'A'] = true;
        bool OK = true;
        for (int j = 0; j < ileLit; ++j)
            if (!ok[j])
                OK = false;
        if (OK)
            odp = (odp + wek2[i]) % MOD;
    }
    cout << odp;
    return 0;
}

#include <iostream>
#include <cstdio>
#include <string>
#include <vector>
#include <set>
#include <map>
#include <queue>
#include <cmath>
#include <algorithm>
#include <sstream>
#include <stack>
#include <cstring>
#include <iomanip>
using namespace std;
#define pb push_back
#define INF 1000000000
#define FOR(i,n) for(int (i)=0;(i)<(n);++(i))
#define FORI(i,n) for(int (i)=1;(i)<=(n);++(i))
#define mp make_pair
#define pii pair<int,int>
#define ll long long
#define vi vector<int>
#define SZ(x) ((int)(x.size()))
#define fi first
#define se second
#define wez(n) int (n); scanf("%d",&(n));
#define wez2(n,m) int (n),(m); scanf("%d %d",&(n),&(m));
#define wez3(n,m,k) int (n),(m),(k); scanf("%d %d %d",&(n),&(m),&(k));
inline void pisz(int n) { printf("%d\n",n); }
template<typename T,typename TT> ostream& operator<<(ostream &s,pair<T,TT> t) {return s<<"("<<t.first<<","<<t.second<<")";}
template<typename T> ostream& operator<<(ostream &s,vector<T> t){FOR(i,SZ(t))s<<t[i]<<" ";return s; }
#define IN(x,y) ((y).find((x))!=(y).end())
#define DBG(vari) cerr<<#vari<<" = "<<(vari)<<endl;
#define ALL(t) t.begin(),t.end()
#define FOREACH(i,t) for (typeof(t.begin()) i=t.begin(); i!=t.end(); i++)
#define TESTS wez(testow)while(testow--)
#define REP(i,a,b) for(int (i)=(a);(i)<=(b);++i)
#define REPD(i,a,b) for(int (i)=(a); (i)>=(b);--i)
#define REMAX(a,b) (a)=max((a),(b));
#define REMIN(a,b) (a)=min((a),(b));

const int MOD = 12345;

typedef int typ;
typedef vector<vector<typ> > macierz;

int ROZM;

void wypisz(const macierz &m) {
   FOR(i,ROZM) {
      FOR(j,ROZM) cout << m[i][j] << " ";
      cout << endl;
   }
}

macierz id() {
   macierz w(ROZM);
   FOR(i,ROZM) {
      w[i].resize(ROZM,0);
      w[i][i] = 1;
   }
   return w;
}

macierz zero() {
   macierz w(ROZM);
   FOR(i,ROZM) w[i].resize(ROZM,0);
   return w;
}

macierz transp(const macierz &m) {
   macierz w = zero();
   FOR(i,ROZM) FOR(j,ROZM) w[i][j]=m[j][i];
   return w;
}

macierz mult_transp(const macierz &m1, const macierz &m2) {
   macierz w = zero(), m3 = transp(m2);
   FOR(i,ROZM) FOR(j,ROZM) {
      ll wyn = 0;
      FOR(k,ROZM) wyn += m1[i][k] * m3[j][k];
      w[i][j] = wyn % MOD;
   }
   return w;
}

macierz potega(const macierz &m, ll k) {
   if (k==0) return id();
   macierz x = potega(m,k/2);
   x = mult_transp(x,x);
   if (k&1) return mult_transp(m,x);
   else return x;
}

set<int> mults[300], goodrests[300]; // dobre reszty (mod prod[i])
int prod[300], pprod[300];

vi decode (int mask) {
   vi w;
   REP(i,'A','Z') w.pb((mask / pprod[i-1]) % prod[i]);
   return w;
}

int encode (vi w) {
   int mask = 0;
   REP(i,'A','Z') mask += pprod[i-1] * w[i-'A'];
   return mask;
}

vi addletter (vi w, char l) {
   w[l-'A']++;
   if (w[l-'A'] == prod[l]) w[l-'A'] = 0;
   return w;
}

int main () {
   ios_base::sync_with_stdio(0);
   ll n;
   int c;
   cin >> n >> c;
   while (c--) {
      string s;
      int mult;
      cin >> s >> mult;
      mults[s[0]].insert(mult);
   }
   int p = 1;
   REP(i,'A','Z') {
      prod[i] = 1;
      FOREACH(it,mults[i]) prod[i] *= *it;
      goodrests[i].insert(0);
      FOREACH(it,mults[i]) for (int x = *it; x < prod[i]; x += *it) goodrests[i].insert(x);
      p *= prod[i];
   }
   pprod['A' - 1] = 1;
   REP(i,'A','Z') pprod[i] = pprod[i-1] * prod[i];

   ROZM = p;

   macierz T = zero();
   FOR(mask,p) REP(l,'A','Z') if (!mults[l].empty()) {
      int mask2 = encode(addletter(decode(mask),l));
      T[mask2][mask]++;
   }

   //DBG(vi(ALL(goodrests['A'])))
   //DBG(7 == encode(decode(7)))
   //wypisz(T);

   macierz Tpot = potega(T,n);
   //wypisz(Tpot);
   // wektor A_n = T^n A_0, gdzie A_0 = (1 0 0 ... 0), rowny jest pierwszej kolumnie Tpot
   ll res = 0;
   FOR(mask,p) {
      // spr. czy maska jest dobra (Zeyad nie zostanie ukarany)
      vi w = decode(mask);
      //DBG(mask)DBG(w)
      bool ok = 1;
      REP(i,'A','Z') if (!IN(w[i-'A'], goodrests[i])) ok = 0;
      if (ok) res += Tpot[mask][0];
      //if (ok) printf("%d is ok\n",mask);
   }
   cout << (res % MOD) << endl;
}

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<vector>
#include<algorithm>

using namespace std;

const int mo=12345;

int s,cnt,num,multi[30],c,pos[30];

long long n;

char st[3];

vector<int> status[125],nowway,v[30];

map< vector <int> , int > id;

struct matrix
{
	int z[125][125];
	matrix()
	{
		memset(z,0,sizeof(z));
	}
	matrix operator*(const matrix &a)const
	{
		matrix ans;
		for (int b=1;b<=s;b++)
			for (int c=1;c<=s;c++)
				for (int d=1;d<=s;d++)
					ans.z[b][c]=(ans.z[b][c]+z[b][d]*a.z[d][c]%mo)%mo;
		return ans;
	}
}m1,m2;

matrix mul(matrix a,long long b)
{
	matrix ans;
	for (int c=1;c<=s;c++)
		ans.z[c][c]=1;
	while (b)
	{
		if (b&1) ans=ans*a;
		a=a*a;
		b>>=1;
	}
	return ans;
}

void dfs(int now)
{
	if (now==cnt)
	{
		num++;
		status[num]=nowway;
		id[nowway]=num;
	}
	else
	{
		for (int a=0;a<multi[now];a++)
		{
			nowway.push_back(a);
			dfs(now+1);
			nowway.pop_back();
		}
	}
}

int gcd(int a,int b)
{
	if (a % b==0) return b;
	else return gcd(b,a % b);
}

int main()
{
	scanf("%I64d%d",&n,&c);
	for (int a=1;a<=c;a++)
	{
		scanf("%s",st);
		int nowv;
		scanf("%d",&nowv);
		v[st[0]-'A'+1].push_back(nowv);
	}
	s=1;
	for (int a=1;a<=26;a++)
		if (v[a].size())
		{
			sort(v[a].begin(),v[a].end());
			v[a].resize(unique(v[a].begin(),v[a].end())-v[a].begin());
			int size=0;
			for (int b=0;b<(int)v[a].size();b++)
			{
				bool able=true;
				for (int c=0;c<b;c++)
					if (v[a][b]%v[a][c]==0) able=false;
				if (able)
				{
					v[a][size]=v[a][b];
					size++;
				}
			}
			v[a].resize(size);
			if (v[a].back()==1) continue;
			int lcm=1;
			for (int b=0;b<(int)v[a].size();b++)
				lcm=lcm*v[a][b]/gcd(v[a][b],lcm);
			s*=lcm;
			multi[cnt]=lcm;
			pos[a]=cnt;
			cnt++;
		}
	dfs(0);
	for (int a=1;a<=num;a++)
	{
		nowway=status[a];
		for (int b=1;b<=26;b++)
			if (v[b].size())
			{
				if (v[b].back()==1) m1.z[a][a]++;
				else
				{
					nowway[pos[b]]++;
					nowway[pos[b]]%=multi[pos[b]];
					int idx=id[nowway];
					m1.z[a][idx]++;
					nowway[pos[b]]+=multi[pos[b]]-1;
					nowway[pos[b]]%=multi[pos[b]];
				}
			}
	}
	m2.z[1][1]=1;
	m2=m2*mul(m1,n);
	int ans=0;
	for (int a=1;a<=num;a++)
	{
		nowway=status[a];
		bool able=true;
		for (int b=1;b<=26;b++)
			if (v[b].size())
			{
				if (v[b].back()==1) continue;
				bool fail=true;
				for (int c=0;c<(int)v[b].size();c++)
					if (nowway[pos[b]]%v[b][c]==0)
					{
						fail=false;
						break;
					}
				if (fail)
				{
					able=false;
					break;
				}
			}
		if (able) ans=(ans+m2.z[1][a])%mo;
	}
	printf("%d\n",ans);

	return 0;
}

#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=1100,mod=12345;

LL n;
int g,m,ok[26],t[26],sz,cnt,w[26],valid[124],ans;
vector<int> vec[26];
struct matrix {
	int arr[124][124];
	int* operator [](int x) { return arr[x]; }
} bit,F;

matrix mul(matrix &A,matrix B,int o=g-1) {
	matrix res;
	for(int i=0;i<=o;++i)
		for(int j=0;j<g;++j) {
			res[i][j]=0;
			for(int k=0;k<g;++k)
				res[i][j]=(res[i][j]+(LL)A[i][k]*B[k][j]%mod)%mod;
		}
	for(int i=0;i<=o;++i)
		for(int j=0;j<g;++j)
			A[i][j]=res[i][j];
}

void work(int val) {
	int cur[26],tmp=val; valid[val]=1;
	for(int i=1;i<=cnt;++i) {
		cur[i]=tmp%t[i], tmp/=t[i];
		bool fl=0;
		for(auto x:vec[w[i]])
			if(cur[i]%x == 0) { fl=1;  break; }
		if(!fl) valid[val]=0;
	}
	for(int i=1,k;i<=cnt;++i) {
		cur[i]=(cur[i]+1)%t[i], k=0;
		for(int j=cnt;j>=1;--j)
			k=k*t[j]+cur[j];
		bit[val][k]=1;
		cur[i]=(cur[i]+t[i]-1)%t[i];
	}
	bit[val][val]=sz;
}
int gcd(int x,int y) { return y?gcd(y,x%y):x; }
int lcm(int x,int y) {
	if(!x) return y;
	return x*y/gcd(x,y);
}
int main() {
	cin>>n>>m;
	for(int i=1;i<=m;++i) {
		char s='!'; int x;
		while(s<'A' || s>'Z') s=getchar();
		scanf("%d",&x);
		if(x == 1 || x == 0) ok[s-'A']=1;
		else vec[s-'A'].push_back(x);
	}
	for(int i=0;i<26;++i) {
		if(ok[i]) { ++sz; continue; }
		if(!vec[i].size()) continue;
		++cnt, w[cnt]=i;
		for(auto x:vec[i]) t[cnt]=lcm(t[cnt],x);
		g=g?g*t[cnt]:t[cnt];
	}
	for(int i=0;i<g;++i) work(i);
	F[0][0]=1;
	for(int i=0;(1ll<<i)<=n;++i) {
		if((1ll<<i)&n) mul(F,bit,0);
		mul(bit,bit);
	}
	if(n == 0) { puts("1"); return 0; }
	for(int i=0;i<g;++i)
		if(valid[i]) ans=(ans+F[0][i])%mod;
	printf("%d",ans);
	return 0;
}

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

struct matrix
{int a[130][130];
};
struct matrix g,f,e;

struct unit
{int x;
 vector<int> w;
};
struct unit a[30];

long long n;
int m,mod=12345,ans;
int b[30],c[30];

bool cmp(struct unit aa,struct unit bb)
{return aa.x>bb.x;
}

int gcd(int i,int j)
{if(j==0)
 	return i;
 else
 	return gcd(j,i%j);
}

matrix operator *(matrix aa,matrix bb)
{matrix ret;
 int i,j,k;
 memset(ret.a,0,sizeof(ret.a));
 for(i=0;i<=123;i++)
 	for(k=0;k<=123;k++)
	 	if(aa.a[i][k])
		{	for(j=0;j<=123;j++)
				ret.a[i][j]=(ret.a[i][j]+aa.a[i][k]*bb.a[k][j]%mod)%mod;
		}
 return ret;
}

matrix fpow(long long j)
{matrix ret=e,t;
 t=g;
 while(j>0)
 {	if(j&1) ret=ret*t;
 	t=t*t;
	j/=2;
 }
 return ret;
}

int main()
{int i,j,x,s,s1,flag;
 char ch[2];
 for(i=0;i<=123;i++)
 	e.a[i][i]=1;
 scanf("%I64d%d",&n,&m);
 for(i=1;i<=m;i++)
 {	scanf("%s%d",ch,&x);
 	if(a[ch[0]-64].x==0)
 		a[ch[0]-64].x=x;
 	else
	 	a[ch[0]-64].x=a[ch[0]-64].x*x/gcd(a[ch[0]-64].x,x);
	a[ch[0]-64].w.push_back(x);
 }
 sort(a+1,a+26+1,cmp);
 for(i=1;i<=26;i++)
 	if(a[i].x==0)
 	{	m=i-1;
 		break;
 	}
 for(i=m;i>=1;i--)
 {	b[i]=1;
 	for(j=i+1;j<=m;j++)
 		b[i]+=(a[j].x-1)*b[j];
 }
 while(c[0]==0)
 {	s=0;
 	for(i=1;i<=m;i++)
 		s+=c[i]*b[i];
	for(i=1;i<=m;i++)
	{	if(c[i]==a[i].x-1)
			s1=s-b[i]*(a[i].x-1);
		else
			s1=s+b[i];
		g.a[s][s1]++;
	}
	i=m;
	while(c[i]==a[i].x-1)
	{	c[i]=0;
		i--;
	}
	c[i]++;
 }
 /*
 for(i=0;i<=10;i++)
 {	for(j=0;j<=10;j++)
 		cout<<g.a[i][j]<<" ";
 	cout<<endl;
 }
 */
 f=fpow(n);
 memset(c,0,sizeof(c));
 while(c[0]==0)
 {	s=0;
 	flag=1;
	for(i=1;i<=m;i++)
 		s+=c[i]*b[i];
 	for(i=1;i<=m;i++)
	{	flag=0;
		for(j=0;j<a[i].w.size();j++)
			if(c[i]%a[i].w[j]==0)
			{	flag=1;
				break;
			}
		if(!flag) break;
	}
	if(flag) ans=(ans+f.a[0][s])%mod;
 	i=m;
 	while(c[i]==a[i].x-1)
 	{	c[i]=0;
 		i--;
 	}
 	c[i]++;
 }
 cout<<ans<<endl;
 return 0;
}

#include<cstdio>
#include<cstring>
#include<algorithm>
#define Mod 12345
using namespace std;
typedef long long ll;
struct Matrix
{
	int num[140][140];
};
int num[30][30], Mul[30], size[30], v[30], b[140];
char str[10001];
ll c;
int n, m;
int gcd(int x, int y) { return y == 0 ? x : gcd(y, x % y); }
Matrix operator * (Matrix& a, Matrix& b)
{
	Matrix c;
	memset(c.num, 0, sizeof(c.num));
    for (int i = 1; i <= n; i ++)
		for (int j = 1; j <= n; j ++)
			for (int k = 1; k <= n; k ++)
            	c.num[i][j] += a.num[i][k] * b.num[k][j], c.num[i][j] %= Mod;
    return c;
}
Matrix Ksm(Matrix get, ll T)
{
	Matrix t, ans;
	memset(t.num, 0, sizeof(t.num));
	memset(ans.num, 0, sizeof(ans.num));
    ans.num[1][1] = 1;
    t = get;
    while (T)
    {
		if (T & 1) ans = ans * t;
        t = t * t;
        T >>= 1;
    }
    return ans;
}
int work()
{
	int ans = 0;
    Matrix mat;
    Mul[0] = 1;
    for (int i = 1; i <= 26; i ++)
        Mul[i] = Mul[i - 1] * size[i];
    n = Mul[26];
    for (int i = 1; i <= n; i ++)
    {
		b[i] = 1;
        for (int j = 1; j <= 26; j ++)
            if (v[j])
            {
				int flag = 0, tmp = i + Mul[j - 1] - 1;
                if (((i - 1) / Mul[j - 1] + 1) % size[j] == 0) tmp -= Mul[j];
                ++ mat.num[i][tmp + 1];
                for (int k = 1; k <= v[j]; k ++)
                    if (((i - 1) / Mul[j - 1]) % num[j][k] == 0) flag = 1;
                b[i] &= flag;
            }
    }
    mat = Ksm(mat, c);
    for (int i = 1; i <= n; i ++)
        if (b[i]) ans += mat.num[1][i], ans %= Mod;
    return ans;
}
int main( )
{
	int x;
    scanf("%I64d %d", &c, &m);
    for (int i = 1; i <= 26; i ++) size[i]=1;
    for (int i = 1;i <= m; i ++)
    {
		scanf("%s", str);
        int get = str[0] - 'A' + 1;
        scanf("%d", &x);
        size[get] *= x / gcd(x, size[get]);
        num[get][++ v[get]] = x;
    }
    printf("%d\n", work() % Mod);
    return 0;
}

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

struct matrix
{int a[130][130];
};
struct matrix g,f,e;

struct unit
{int x;
 vector<int> w;
};
struct unit a[30];

long long n;
int m,ans;
int b[30],c[30];
const int mod=12345;

bool cmp(struct unit aa,struct unit bb)
{return aa.x>bb.x;
}

int gcd(int i,int j)
{if(j==0)
    return i;
 else
    return gcd(j,i%j);
}

matrix operator *(matrix aa,matrix bb)
{matrix ret;
 int i,j,k;
 memset(ret.a,0,sizeof(ret.a));
 for(i=0;i<=123;i++)
    for(j=0;j<=123;j++)
    {   ret.a[i][j]=0;
        for(k=0;k<=123;k++)
        {   ret.a[i][j]=(ret.a[i][j]+aa.a[i][k]*bb.a[k][j]);
            if((k&7)==0)
                ret.a[i][j]%=mod;
        }
        ret.a[i][j]%=mod;
    }
 return ret;
}

matrix fpow(long long j)
{matrix ret=e,t;
 t=g;
 while(j>0)
 {  if(j&1) ret=ret*t;
    t=t*t;
    j/=2;
 }
 return ret;
}

int main()
{int i,j,x,s,s1,flag;
 char ch[2];
 for(i=0;i<=123;i++)
    e.a[i][i]=1;
 scanf("%I64d%d",&n,&m);
 for(i=1;i<=m;i++)
 {  scanf("%s%d",ch,&x);
    if(a[ch[0]-64].x==0)
        a[ch[0]-64].x=x;
    else
        a[ch[0]-64].x=a[ch[0]-64].x*x/gcd(a[ch[0]-64].x,x);
    a[ch[0]-64].w.push_back(x);
 }
 sort(a+1,a+26+1,cmp);
 for(i=1;i<=26;i++)
    if(a[i].x==0)
    {   m=i-1;
        break;
    }
 for(i=m;i>=1;i--)
 {  b[i]=1;
    for(j=i+1;j<=m;j++)
        b[i]+=(a[j].x-1)*b[j];
 }
 while(c[0]==0)
 {  s=0;
    for(i=1;i<=m;i++)
        s+=c[i]*b[i];
    for(i=1;i<=m;i++)
    {   if(c[i]==a[i].x-1)
            s1=s-b[i]*(a[i].x-1);
        else
            s1=s+b[i];
        g.a[s][s1]++;
    }
    i=m;
    while(c[i]==a[i].x-1)
    {   c[i]=0;
        i--;
    }
    c[i]++;
 }
 f=fpow(n);
 memset(c,0,sizeof(c));
 while(c[0]==0)
 {  s=0;
    flag=1;
    for(i=1;i<=m;i++)
        s+=c[i]*b[i];
    for(i=1;i<=m;i++)
    {   flag=0;
        for(j=0;j<a[i].w.size();j++)
            if(c[i]%a[i].w[j]==0)
            {   flag=1;
                break;
            }
        if(!flag) break;
    }
    if(flag) ans=(ans+f.a[0][s])%mod;
    i=m;
    while(c[i]==a[i].x-1)
    {   c[i]=0;
        i--;
    }
    c[i]++;
 }
 cout<<ans<<endl;
 return 0;
}

/*2011.8.20*/
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <vector>
#include <string>
#include <map>
#include <set>
#include <algorithm>
#include <assert.h>
using namespace std;
#define PL printf("%d\n", __LINE__);
#define MM(a, b) memset(a, b, sizeof(a));
#define For(i, a) for (int i = 0; i < a; i++)
#define foru(i, a, b) for (int i = a; i <= b; i++)
#define ford(i, a, b) for (int i = a; i >= b; i--)
#define debug(a) printf("(ln %d) %s = %d\n", __LINE__, #a, (a))
#define inf 1000000000
#define linf 10000000000000000LL
#define pb push_back
#define mp make_pair
#define eps 1e-10
#define Walk(u) for (elist l = de[u]; l; l = l->next)
#define gi getint()
#define bgn begin
#define fi first
#define se second
#define All(x) x.begin(), x.end()
typedef long long LL;
typedef pair<int, int> pii;
typedef vector<int> vi;

int getint() {
	char ch;
	int res;
	while (ch = getchar(), !isdigit(ch) && ch != '-');
	bool f = ch == '-';
	if (f) res = 0; else res = ch - '0';
	while (isdigit(ch = getchar())) res = res * 10 + ch - '0';
	return f ? -res : res;
}

#define maxn 129
#define P 12345
int n;
struct Mat {
	int a[maxn][maxn];
	Mat() {MM(a, 0);}
	void Unit() {For (i, n) a[i][i] = 1;}
};
Mat operator *(const Mat &a, const Mat &b) {
	Mat c;
	For (i, n) For (j, n) For (k, n) c.a[i][j] = (c.a[i][j] + (LL)a.a[i][k] * b.a[k][j]) % P;
	return c;
}

Mat Power(Mat a, LL k) {
	Mat res; res.Unit();
	for (; k; k >>= 1) {
		if (k & 1) res = res * a;
		a = a * a;
	}
	return res;
}

char getord() {
	char ch;
	while (!isalpha(ch = getchar()));
	return ch;
}

vector<int> mul[maxn];
int N, M[maxn]; LL m;
int ans;

vector<int> Get(int a) {
	vi res;
	For (i, N) {
		res.pb(a % M[i]);
		a = a / M[i];
	}
	return res;
}

Mat G;

int Check(int a) {
	vi p = Get(a);
	For (i, N) {
		bool flg = false;
		For (j, mul[i].size()) if (p[i] % mul[i][j] == 0) flg = true;
		if (!flg) return false;
	}
	return true;
}

int Get(vi p) {
	int res = 0;
	int MMM = 1;
	For (i, N) {
		res = res + p[i] * MMM;
		MMM *= M[i];
	}
	return res;
}

int main() {
//	freopen("data.in", "r", stdin);
	scanf("%I64d%d", &m, &n);
	foru (i, 1, n) {
		char ch = getord();
		ch -= 'A';
		mul[(int)ch].pb(getint());
	}
	N = 0;
	For (i, 26) if (mul[i].size()) mul[N++] = mul[i];
	For (i, N) sort(mul[i].begin(), mul[i].end()),
			mul[i].resize(unique(All(mul[i])) - mul[i].begin());
	n = 1;
	For (i, N) M[i] = 1;
	For (i, N) For (j, mul[i].size()) n = n * mul[i][j], M[i] *= mul[i][j];
	For (i, n) {
		vi p = Get(i);
		For (k, N) {
			vi q = p;
			q[k]++; q[k] %= M[k];
			int j = Get(q);
			G.a[i][j]++;
		}
	}
	G = Power(G, m);
	ans = 0;
	For (i, n)
		ans = (ans + (int)Check(i) * G.a[0][i]) % P;
	printf("%d\n", ans);
	return 0;
}

#include <cstdio>
#include <vector>
#include <iostream>
#define MOD 12345
using namespace std;
struct matrix
{
  int a[150][150];
}matmp,mat,matans,C;
struct box
{
  int rem[26];
}s[150];
int m,rem[26],ans,a[26]; long long int n;
vector<int> ok[26];
vector<int>::iterator it;
void add_state()
{
  m++;
  for(int i=0;i<26;i++) s[m].rem[i] = rem[i];
}
void dfs(int p)
{
  if(p == 26){
    add_state();
    return;
  }
  if(!ok[p].size()) {dfs(p+1);return;}
  for(int i=0;i<a[p];i++)
    rem[p]=i,dfs(p+1);
  return;
}
int trans(int s1,int s2)
{
  int cnt=0,i,cnt1=0;
  for(i=0;i<26 && cnt<=1;i++)
    if(ok[i].size())
      {
	if(a[i] == 1) {cnt1++;continue;}
	if(s[s2].rem[i] == (s[s1].rem[i]+1)%a[i]) cnt++;
	else if(s[s1].rem[i] == s[s2].rem[i]) continue;
	else return 0;
      }
  if(cnt == 1) return 1;
  if(cnt1 && cnt==0) return cnt1;
  return 0;
}
bool chk(int s1)
{
  for(int i=0;i<26;i++)
    if(ok[i].size())
      {
	for(it=ok[i].begin();it!=ok[i].end();it++)
	  if(s[s1].rem[i]%(*it) == 0)
	    break;
	if(it == ok[i].end()) return false;
      }
  return true;
}
void multi(matrix A,matrix B)
{
  int i,j,k;
  for(i=0;i<=m;i++)
    for(j=0;j<=m;j++)
      C.a[i][j] = 0;
  for(k=0;k<=m;k++)
    for(i=0;i<=m;i++)
      for(j=0;j<=m;j++)
	C.a[i][j] = (A.a[i][k]*B.a[k][j]+C.a[i][j])%MOD;
}
void matpow(long long int x)
{
  long long int b; int i,j;
  for(i=0;i<=m;i++) for(j=0;j<=m;j++) matans.a[i][j]=0;
  for(i=0;i<=m;i++) matans.a[i][i] = 1;
  for(b=1;b<=x;b*=2)
    {
      if(b & x)
	{
	  multi(matans,mat);
	  matans = C;
	}
      multi(mat,mat);
      mat = C;
    }
}
int main()
{
  //freopen("input.txt","r",stdin);
  //freopen("output.txt","w",stdout);
  int i,j,c,x; char ch;
  cin>>n>>c;
  for(i=0;i<26;i++) a[i] = 1;
  for(i=1;i<=c;i++)
    {getchar();
      scanf("%c",&ch);
      scanf("%d",&x);
      ok[ch-'A'].push_back(x);
      a[ch-'A'] *= x;
    }
  dfs(0);
  for(i=1;i<=m;i++)
    for(j=1;j<=m;j++)
      mat.a[i][j] = trans(i,j);
  matpow(n);
  for(i=1;i<=m;i++)
    if(chk(i))
      ans = (ans+matans.a[1][i])%MOD;
  cout<<ans;
}

#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
using namespace std;
const int mod=12345;
typedef long long LL;
int N;

struct Mat{
	int v[150][150];
	int* operator [](int id){
		return v[id];
	}
} mat;
Mat operator *(Mat& a,Mat &b){
	Mat c;
	memset(&c,0,sizeof(c));
	for(int i = 0; i < N; i++)
		for(int j = 0; j < N; j++)
			for(int k = 0; k < N; k++)
				c[i][j]=(c[i][j] + a[i][k] * b[k][j])%mod;
	return c;
}
map<vector<int>,int> m;
bool in[100], allow[100][150],ans[150];
int _lcm[100];
LL n;
int initMat(const vector<int>& v){
	map<vector<int>,int>::iterator it = m.find(v);

	if (it != m.end())
		return it->second;
	int id = N++;
	ans[id] = true;
	m.insert(make_pair(v,id));
	for (int i = 0; i < 26; i++)
		if (in[i]) {
			vector<int> _next(v);
			_next[i] = (_next[i] + 1) % _lcm[i];
			mat[id][initMat(_next)]++;
		}

	for (int i = 0; i < 26; i++)
		if (in[i])
			ans[id] = ans[id] && allow[i][v[i]];

	return id;
}
int gcd(int x,int y){
	return y?gcd(y,x%y):x;
}
int main(){
	int m;
	scanf("%I64d%d",&n,&m);
	for(int i = 1; i <= m; i++){
		char tmp[5];int x = 0;
		scanf("%s%d",tmp,&x);
		allow[tmp[0]-'A'][x] = true;
		in[tmp[0]-'A'] = true;
	}

	for(int i = 0; i<26;i++){
		_lcm[i]=1;
		for(int j = 1; j < 123; j++)
			if(allow[i][j])
				_lcm[i] = ((LL)_lcm[i]*j)/gcd(_lcm[i],j) ;

		for(int j = 122; j > 0; j--)
			if(allow[i][j])
				for(int k = j; k < 123; k += j)
					allow[i][k]=true;
		allow[i][0] = true;
	}

	initMat(vector<int>(26));
	Mat res;
	memset(&res,0,sizeof(res));
	for(int i = 0; i < 130; i++)
		res[i][i] = 1;

	for(int i = 63; i >= 0; i--){
		res = res * res;
		if((n>>i)&1)
			res = res * mat;
	}
	int Ans = 0;
	for(int i = 0; i < N; i++)
		if(ans[i])
			Ans = (Ans + res[0][i]) % mod;
	printf("%d\n",Ans);
}

#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define ULL unsigned long long
const ULL SEED = 439;
const int MOD = 12345;
int read()
{
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
    return num*flag;
}
int m,ans,cnt,t[30];
ULL n,Pow[30]={1},_hash[300];
map<ULL,int> mp;
vector<int> l[30];
struct node
{
	int c[30];
	node() {memset(c,0,sizeof c);}
}a[300],b;
struct Matrix
{
	int n,m,a[300][300];
	Matrix () {n=m=0,memset(a,0,sizeof a);}
	Matrix operator * (const Matrix &B) const
	{
		Matrix res;
		res.n=n,res.m=B.m;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				for(int k=1;k<=B.m;k++)
					res.a[i][k]=(res.a[i][k]+a[i][j]*B.a[j][k])%MOD;
		return res;
	}
}mat;
void dfs(int x,ULL Hash,node now)
{
	if(x==27)
	{
		mp[Hash]=++cnt;
		_hash[cnt]=Hash;
		a[cnt]=now;
		return ;
	}
	dfs(x+1,Hash*SEED,now);
	for(int i=1;i<t[x];i++)
	{
		now.c[x]=i;
		dfs(x+1,Hash*SEED+i,now);
	}
}
void cal(int x,ULL Hash)
{
	if(x==27)
	{
		ans=(ans+mat.a[1][mp[Hash]])%MOD;
		return ;
	}
	cal(x+1,Hash*SEED);
	for(int i=1;i<t[x];i++)
	{
		bool flag=0;
		for(int j=0;j<l[x].size();j++)
			if(i%l[x][j]==0)
			{
				flag=1;
				break;
			}
		if(flag)
			cal(x+1,Hash*SEED+i);
	}
}
Matrix ksm(Matrix A,ULL b)
{
	Matrix res;
	res.n=res.m=A.n;
	for(int i=1;i<=A.n;i++)
		res.a[i][i]=1;
	while(b>0)
	{
		if(b&1) res=res*A;
		A=A*A;
		b>>=1;
	}
	return res;
}
int main()
{
	scanf("%llu",&n);m=read();
	if(n==0)
    {
        printf("1\n");
        return 0;
    }
    if(m==0)
    {
        printf("0\n");
        return 0;
    }
	for(int i=1;i<=26;i++)
		Pow[i]=Pow[i-1]*SEED;
	for(int i=1;i<=m;i++)
	{
		char c;scanf("%s",&c);
		int u=c-'A'+1,x=read();
		if(!t[u]) t[u]=x;
		else t[u]*=x;
		l[u].push_back(x);
	}
	dfs(1,0,b);
	for(int i=1;i<=cnt;i++)
	{
		for(int j=1;j<=26;j++)
		{
			if(t[j]==0) continue;
			ULL to=_hash[i]+Pow[26-j];
			if(a[i].c[j]==t[j]-1)
				to-=t[j]*Pow[26-j];
			mat.a[i][mp[to]]++;
		}
	}
	mat.n=mat.m=cnt;
	mat=ksm(mat,n);
	cal(1,0);
	printf("%d\n",ans);
}

//lxrtxdy!
#include <cstdio>
#include <vector>
#define maxn 1010
const int mod = 12345;
inline int min(int a, int b) {return a < b ? a : b;}
inline int max(int a, int b) {return a > b ? a : b;}
inline void up(int &a, int b) {if ((a += b) >= mod) a -= mod;}
inline long long pw(long long base, long long p) {
    base %= mod;
    long long res = 1;
    for (; p; p >>= 1, base = base * base % mod) if (p & 1) res = res * base % mod;
    return res;
}

int __sz = 1;
struct matrix {
    #define __M 150
    #define M __sz
    int s[__M][__M];
    inline matrix() {
        __builtin_memset(s, 0, sizeof s);
    }
    inline friend matrix operator * (const matrix &lhs, const matrix &rhs) {
        matrix res;
        for (register int i = 0; i < M; i++) {
            for (register int j = 0; j < M; j++) {
                long long tmp = 0;
                for (register int k = 0; k < M; k++) tmp += static_cast<long long> (lhs.s[i][k]) * rhs.s[k][j];
                res.s[i][j] = tmp % mod;
            }
        }
        return res;
    }
    #undef __M
    #undef M
} BASE, RES;

long long n;
int m;
int mp[300], ret[300], __name, prod[300];
int base[300];
std::vector<int> v[300];
inline int get(int x, int i) {return x / base[i - 1] % prod[i];}
inline bool check(int x) {
    for (int i = 1; i <= __name; i++) {
        bool find = false;
        int now = get(x, i);
        for (std::vector<int>::iterator it = v[i].begin(); it != v[i].end(); it++) if (now % *it == 0) {
            find = true;
            break;
        }
        if (!find) return false;
    }
    return true;
}

int main() {
    scanf("%lld%d", &n, &m);
    for (int i = 1, x, ch; i <= m; i++) {
        char __ch;
        scanf("%1s%d", &__ch, &x); ch = static_cast<int>(__ch);
        if (!mp[ch]) mp[ch] = ++__name, ret[__name] = ch, prod[__name] = 1;
        prod[mp[ch]] *= x;
        v[mp[ch]].push_back(x);
        __sz *= x;
    }
    base[0] = 1; for (int i = 1; i <= __name; i++) base[i] = base[i - 1] * prod[i];
    for (int i = 0; i < __sz; i++) {
        for (int j = 1; j <= __name; j++) {
            int now = get(i, j), nxt = (now + 1) % prod[j];
            up(BASE.s[i][i + (nxt - now) * base[j - 1]], 1);
        }
    }
    RES.s[0][0] = 1;
    for (; n; n >>= 1, BASE = BASE * BASE) if (n & 1) RES = RES * BASE;
    int ans = 0;
    for (int i = 0; i < __sz; i++) if (check(i)) up(ans, RES.s[0][i]);
    printf("%d\n", ans);
    return 0;
} //hellobig_tq
//orzlxr!

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define ll long long
#define mod 12345
#define N 1005
#define M 125
ll n;
int m,d=1;
int mat[M][M],now[M][M],ans[M][M];
int p[N];
struct node
{
    char c;int d;
    bool operator<(node b)const{return c==b.c?d<b.d:c<b.c;}
}A[N];
void cg(int a,int *p)
{
    for(int i=m;i>=1;i--)
    {
        p[i]=a%A[i].d;
        a/=A[i].d;
    }
}
void cg(int *p,int &a)
{
    a=0;
    for(int i=1;i<=m;i++)
    {
        a*=A[i].d;
        a+=p[i];
    }
}
void mul(int A[M][M],int B[M][M])
{
    int C[M][M]={{}};
    for(int i=0;i<d;i++)
        for(int j=0;j<d;j++)
            for(int k=0;k<d;k++)
                C[i][j]=(C[i][j]+A[i][k]*B[k][j])%mod;
    for(int i=0;i<d;i++)
        for(int j=0;j<d;j++)
            A[i][j]=C[i][j];
}
void ksm(ll k)
{
    if(!k)return;
    ksm(k/2);
    mul(now,now);
    if(k&1)mul(now,mat);
}
int main()
{
    scanf("%I64d%d",&n,&m);// !!!!!
    for(int i=1;i<=m;i++)
    {
        char S[10];
        scanf("%s",S);
        A[i].c=S[0];
        scanf("%d",&A[i].d);
        d*=A[i].d;
    }
    sort(A+1,A+m+1);
    for(int i=0;i<d;i++)
    {
        now[i][i]=1;
        cg(i,p);
        for(int j=1;j<=m;j++)
        {
            p[j]++;p[j]%=A[j].d;
            if(A[j+1].c!=A[j].c)
            {
                int a;
                cg(p,a);
                mat[a][i]++;
                for(int k=j;;k--)
                {
                    p[k]--;if(p[k]<0)p[k]+=A[k].d;
                    if(A[k-1].c!=A[k].c)break;
                }
            }
        }
    }
    ksm(n);
    ans[0][0]=1;
    mul(ans,now);
    int sum=0;
    for(int i=0;i<d;i++)
    {
        cg(i,p);
        int flg=1;
        for(int j=1;j<=m;j++)
        {
            if(p[j]==0)flg=0;
            if(A[j+1].c!=A[j].c)
            {
                if(flg)
                {
                    sum-=ans[0][i];
                    break;
                }
                flg=1;
            }
        }
        sum+=ans[0][i];
        sum%=mod;
    }
    printf("%d\n",sum);
}

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author Ankur Dua
 */

#include <iostream>
#include <fstream>

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
ll mod=1000000007;
ll *fact, *ifact;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template<typename T1, typename T2>
istream& operator >>(istream& cin, pair<T1, T2> &p){
	cin>>p.first>>p.second;
	return cin;
}
using namespace std;

vector<vector<ll>> operator *(vector<vector<ll>> &a, vector<vector<ll>> &b){
	int n=a.size();
	vector<vector<ll>> ans(n, vector<ll>(n));
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			ll &val=ans[i][j];
			for(int k=0;k<n;k++){
				val+=a[i][k]*b[k][j];
			}
			val%=12345;
		}
	}
	return ans;
}
class DCrimeManagement {
public:

	void solve(std::istream& cin, std::ostream& cout) {
		ll n, c;
		cin>>n>>c;
		if(n==0){
			cout<<1<<endl;
			return;
		}
		if(c==0){
			cout<<0<<endl;
			return;
		}
		vector<vector<int>> v(26);
		for(int i=0;i<c;i++){
			char c;
			int x;
			cin>>c>>x;
			v[c-'A'].push_back(x);
		}
		v.resize(remove_if(v.begin(), v.end(), [](vector<int> x){return x.empty();})-v.begin());
		vector<int> product(v.size());
		for(int i=0;i<v.size();i++){
			product[i]=1;
			for(int x:v[i])
				product[i]=(product[i]*x)/__gcd(product[i], x);
		}
		int m=product.size();
		vector<vector<int>> ways;
		ways.push_back(vector<int>());
		for(int x:product){
			vector<vector<int>> ways2;
			for(int i=0;i<x;i++){
				for(auto way:ways){
					way.push_back(i);
					ways2.push_back(way);
				}
			}
			swap(ways, ways2);
		}

		int sz=ways.size();
		map<vector<int>, int> mp;
		for(int i=0;i<ways.size();i++)
			mp[ways[i]]=i;
		vector<vector<ll>> mat(sz, vector<ll>(sz));
		for(int i=0;i<sz;i++){
			for(int j=0;j<m;j++){
				vector<int> way=ways[i];
				way[j]--;
				if(way[j]<0)
					way[j]+=product[j];
				int nextWay=mp[way];
				mat[i][nextWay]++;
			}
		}

		vector<vector<ll>> ans(sz, vector<ll>(sz));
		for(int i=0;i<sz;i++)ans[i][i]=1;
		while(n){
			if(n&1){
				ans=ans*mat;
			}
			n>>=1;
			mat=mat*mat;
		}
		ll sum=0;
		for(int i=0;i<sz;i++){
			bool valid=true;
			vector<int> way=ways[i];
			for(int j=0;j<m;j++){
				bool flag=false;
				for(int x:v[j])
					if(way[j]%x==0)
						flag=true;
				valid=valid&&flag;
			}
			if(valid)
				sum+=ans[i][0];
		}
		cout<<(sum%12345)<<endl;
	}
};

int main() {
	DCrimeManagement solver;
	std::ios::sync_with_stdio(false);
	std::cin.tie(NULL);
	std::cout.tie(NULL);
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
	return 0;
}

#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <queue>
#include <vector>
#include <cstdio>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>

using namespace std;

const int max_n = 131, mod = 12345;

long long n;
int m, C, cnt[max_n], l[max_n], r[max_n], num[max_n];
vector<int> v[max_n], v1;
map<vector<int>, int> q1;
map<int, vector<int> > q2;

void rec(int poz) {
    if (num[poz] == 0) {
        q1[v1] = C;
        q2[C] = v1;
        ++C;
        return;
    }
    int c = num[poz];
    for (int i = 0; i < v[c][poz - l[c]]; ++i) {
        v1[poz] = i;
        rec(poz + 1);
    }
}

struct matrix {
    vector<vector<int> > v;
    matrix() {
    }
    matrix(int n, int m) {
        v.resize(n, vector<int>(m, 0));
    }
    matrix operator * (const matrix &m) const {
        matrix res(v.size(), m.v[0].size());
        for (int i = 0; i < res.v.size(); ++i) {
            for (int j = 0; j < res.v[i].size(); ++j) {
                for (int k = 0; k < v[i].size(); ++k) {
                    res.v[i][j] += 1LL * v[i][k] * m.v[k][j];
                    res.v[i][j] %= mod;
                }
            }
        }
        return res;
    }
    void write(const string &s = "") const {
        for (int i = 0; i < v.size(); ++i) {
            for (int j = 0; j < v[i].size(); ++j) {
                cout << v[i][j] << " ";
            }
            cout << endl;
        }
    }
};

matrix power(matrix a, long long b) {
    if (b == 0) {
        matrix res(a.v.size(), a.v.size());
        for (int i = 0; i < res.v.size(); ++i) {
            res.v[i][i] = 1;
        }
        return res;
    }
    if (b % 2 == 0) {
        return power(a * a, b / 2);
    }
    return a * power(a, b - 1);
}

matrix A, B;

int main() {
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    cin >> n >> m;
    while (m--) {
        char c;
        int x;
        cin >> c >> x;
        v[c].push_back(x);
    }
    for (char c = 'A'; c <= 'Z'; ++c) {
        sort(v[c].begin(), v[c].end());
        v[c].erase(unique(v[c].begin(), v[c].end()), v[c].end());
        cnt[c] = cnt[c - 1] + v[c].size();
        l[c] = cnt[c - 1];
        r[c] = cnt[c] - 1;
        for (int i = l[c]; i <= r[c]; ++i) {
            num[i] = c;
            v1.push_back(0);
        }
    }
    rec(0);
    A = matrix(1, C);
    B = matrix(C, C);
    A.v[0][0] = 1;
    for (int i = 0; i < C; ++i) {
        v1 = q2[i];
        for (char c = 'A'; c <= 'Z'; ++c) {
            if (v[c].size()) {
                for (int j = l[c]; j <= r[c]; ++j) {
                    ++v1[j];
                    v1[j] %= v[c][j - l[c]];
                }
                int num = q1[v1];
                ++B.v[i][num];
                for (int j = l[c]; j <= r[c]; ++j) {
                    --v1[j];
                    v1[j] += v[c][j - l[c]];
                    v1[j] %= v[c][j - l[c]];
                }
            }
        }
    }
    B = power(B, n);
    A = A * B;
    int ans = 0;
    for (int i = 0; i < C; ++i) {
        v1 = q2[i];
        int f = 0;
        for (char c = 'A'; c <= 'Z'; ++c) {
            int ff = 0;
            for (int j = l[c]; j <= r[c]; ++j) {
                if (v1[j] == 0) {
                    ff = 1;
                    break;
                }
            }
            if (l[c] <= r[c] && ff == 0) {
                f = 1;
                break;
            }
        }
        if (f == 0) {
            ans = (ans + A.v[0][i]) % mod;
        }
    }
    cout << ans << endl;
    return 0;
}

#include <string>
#include <vector>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstring>
#include <fstream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <iterator>
#include <cassert>
#include <stack>
#include <queue>
#include <ctime>
#include <vector>
#include <map>
#include <set>
#include <utility>

using namespace std;

#define FORALL(i,a,b) for (int i = (a); i <= (b); i++)
#define FOR(i,n) for (int i=0;i<n;i++)
#define FORB(i,a,b) for (int i = (a); i >= (b); i--)
#define FORIN(it,type,b) for(type::iterator it = (b).begin(); it != (b).end(); it++)
#define pb push_back
#define mp make_pair
typedef long long ll;
typedef long double ld;

#define in cin
#define out cout
#define dout if(true) cout

#define MAXC 30
#define MOD 12345
#define MAXH 150
#define MAXB 4000

int smemo[MAXH][MAXB];
int M[MAXC];
vector<ll> H;

set<int> mset[MAXC];

int B[MAXB][MAXC];	//B[k] = the k'th assignment set
int numB;

int gcd(int a, int b){
	if (b==0) return a;
	return gcd(b,a%b);
}

int lcm(int a, int b){
	return a/gcd(a,b)*b;
}

int cur[MAXC];
void makebset(int i){
	if (i==26){
		FOR(j,26) B[numB][j] = cur[j];
		numB++;
		return;
	}

	FOR(k,M[i]){
		cur[i] = k;
		makebset(i+1);
	}

	if (M[i] == 0) cur[i] = 0, makebset(i+1);
}

bool equal(int* P, int* Q){
	FOR(i,26) if (P[i] != Q[i]) return false;
	return true;
}

int subtract(int* P, int* Q){
	int ans[26];
	FOR(i,26) {
		ans[i] = (P[i]-Q[i]+M[i]);
		if (M[i] > 0) ans[i] %= M[i];
	}

	FOR(k,numB){
		if (equal(ans,B[k])) return k;
	}

	throw "BAD!";
}

//can i have this one and only this?
bool validone(int i, int b){
	FOR(j,26){
		if (B[b][j] == 0) continue;
		int x = B[b][j];
		if ((j==i) && (x != 1)) return false;
		if ((j!=i) && (x != 0)) return false;
	}
	if (b==0) return M[i] == 1;
	return true;
}

void makehset(ll N){
	queue<ll> Q;
	Q.push(N);
	while(!Q.empty()){
		ll i = Q.front();Q.pop();
		if (i==0) continue;
		if (find(H.begin(),H.end(),i) != H.end()) continue;
		H.pb(i);
		sort(H.begin(),H.end());
		Q.push(i/2);
		Q.push(i-i/2);
	}

	int S = H.size();
}

int S(ll n, int b){
	int i = find(H.begin(), H.end(), n) - H.begin();
	int j = b;//find(B.begin(), B.end(), n) - B.begin();

	assert(n != 0);
	assert(H[i] == n);

	int & ans = smemo[i][j];
	if (ans != -1) return ans;

	if (n==1){
		ans = 0;
		FOR(i,26){
			if (M[i] == 0) continue;
			if (validone(i,b)) ans++;
		}
		return ans;
	}
	ans = 0;
	for (int k=0;k<numB;k++){
		ll c = subtract(B[j],B[k]);
		ans += S(n/2,k)*S(n-n/2,c);
		ans %= MOD;
	}
	return ans;
}

bool countable(int b){
	FOR(j,26){
		if (M[j] == 0) continue;
		int val = (B[b][j]%M[j]);
		bool found = false;
		FORIN(it,set<int>,mset[j]){
			if (val == (*it)) found = true;
			if ((*it) == 0) continue;
			if ((val % (*it)) == 0) found = true;
		}
		if (!found) return false;
	}
	return true;
}

int main()
{
	ll N;
	int C;
	in >> N >> C;
	memset(M,0,sizeof(M));
	FOR(i,C){
		string x;
		int v;
		in >> x >> v;
		int& m = M[x[0]-'A'];
		if (m==0) m = v;
		else m = lcm(m,v);
		mset[x[0]-'A'].insert(v);
	}
	FOR(i,26) mset[i].insert(0);

	memset(smemo,-1,sizeof(smemo));

	if (N==0){
		cout << 1 << endl;
		return 0;
	}

	makehset(N);
	numB = 0; makebset(0);
	int ans = 0;
	FOR(k,numB){
		if (!countable(k)) continue;
		ans += S(N,k);
		ans %= MOD;
	}
	cout << ans << endl;
}

#include<bits/stdc++.h>
using namespace std;
const int N = 129, Mod = 12345;
struct Matrix
{
    int n, m, A[N][N];
    Matrix(int _n, int _m) :
        n(_n) , m(_m) {memset(A, 0, sizeof(A));}
    Matrix operator * (const Matrix &X)
    {
        Matrix R(n, X.m);
        for (int i = 0; i < n; i ++)
            for (int j = 0; j < X.m; j ++)
            {
                long long tot = 0;
                for (int k = 0; k < m; k ++)
                    tot += 1ll * A[i][k] * X.A[k][j];
                R.A[i][j] = tot % Mod;
            }
        return (R);
    }
    Matrix operator ^ (const long long &pw)
    {
        Matrix R(n, n), T = *this;
        for (int i = 0; i < n; i++)
            R.A[i][i] = 1;
        for (long long b = pw; b; b >>= 1, T = T * T)
            if (b & 1) R = R * T;
        return (R);
    }
};
int q, m = 1, C[30];
bool M[30][N];
long long n;
vector < int > Get(int a)
{
    int c = 1;
    vector < int > ret;
    for (int i = 0; i < 26; i++)
        if (C[i])
            ret.push_back(a % (c * C[i]) / c), c *= C[i];
    return (ret);
}
int main()
{
    cin >> n >> q;
    for (; q; q --)
    {
        char ch; int c;
        cin >> ch >> c;
        ch -= 'A';
        if (!C[ch])
            C[ch] = c;
        else
            C[ch] *= c;
        for (int i = c; i < N; i += c)
            M[ch][i] = 1;
        M[ch][0] = 1;
        m *= c;
    }
    vector < int > f;
    for (int i = 0; i < 26; i++)
        if (C[i]) f.push_back(i);
    Matrix A(1, m), T(m, m);
    A.A[0][0] = 1;
    for (int i = 0; i < m; i++)
        for (int j = 0; j < m; j++)
        {
            vector < int > a = Get(i), b = Get(j);
            int cnt = 0, ones = 0;
            for (int k = 0; k < a.size(); k ++)
            {
                if (a[k] != b[k])
                {
                    cnt ++;
                    if ((a[k] + 1) % C[f[k]] != b[k])
                        cnt += N;
                }
                else if ((a[k] + 1) % C[f[k]] == b[k])
                    ones ++;
            }
            if (cnt == 1)
                T.A[i][j] = 1;
            if (cnt == 0)
                T.A[i][j] = ones;

        }
    T = T ^ n; A = A * T;
    long long tot = 0;
    for (int i = 0; i < m; i++)
    {
        bool w = 1;
        vector < int > a = Get(i);
        for (int k = 0; k < a.size(); k ++)
            if (!M[f[k]][a[k]])
                w = 0;
        if (w) tot += A.A[0][i];
    }
    return cout << tot % Mod, 0;
}

#include <bits/stdc++.h>
#ifdef _MSC_VER
#define __builtin_popcount (int)__popcnt
#define __builtin_popcountll (int)__popcnt64
#define __builtin_clz (int)__lzcnt
#define $ system("pause")
#define gp_hash_table unordered_map
#else
#pragma GCC optimize("Ofast")
#pragma GCC optimize("unroll-loops")
#pragma GCC target("sse,sse2,sse3,ssse3,sse4")
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace __gnu_pbds;
#define $
//#define USACO
//#define IOI_style
#endif

using namespace std;

typedef long long ll;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef long double ld;
typedef complex<double> point;

#define MOD 12345
#define MAXN 123
#define LG 20
#define inf int(1e9 + 100)

#define rep(i, j, k) for (int i = j; i < k; i++)
#define for_all(x) x.begin(), x.end()
#define lid id << 1
#define rid id << 1 | 1
#define lch l, mid, lid
#define rch mid, r, rid
#define pb push_back
#define X first
#define Y second
#define re real()
#define im imag()

template <typename S, typename T>
inline ostream &operator<<(ostream &out, const pair<S, T> &p)
{
	return out << "( " << p.X << " , " << p.Y << " )";
}
template <typename S>
inline ostream &operator<<(ostream &out, const vector<S> &p)
{
	for (auto &e : p) out << e; return out;
}
template <typename T, typename S>
inline T smin(T &a, const S &b) { return a > b ? a = b : a; }
template <typename T, typename S>
inline T smax(T &a, const S &b) { return a < b ? a = b : a; }
inline double dot(const point l, const point r) { return l.re * r.re + l.im * r.im; }
inline double cross(const point l, const point r) { return l.re * r.im - l.im * r.re; }
ll po(ll v, ll u) { return u ? (po(v * v % MOD, u >> 1) * (u & 1 ? v : 1) % MOD) : 1; }
template<class T> inline void add(T &l, const T &r) { l = (l + r) % MOD; }
ll gcd(ll v, ll u) { return u ? gcd(u, v % u) : v; }

ll n;
int c;
vector<int> vec, o[30];

struct Mat {
	int n, m;
	ll arr[MAXN][MAXN];
	Mat(int n, int m, int z = 0) : n(n), m(m) {
		memset(arr, 0, sizeof(arr));
		rep(i, 0, min(n, m))
			arr[i][i] = z;
	}
};

inline ostream &operator<<(ostream &out, Mat &p)
{
	rep(i, 0, p.n) {
		rep(j, 0, p.m)
			cout << p.arr[i][j] << ' ';
		cout << endl;
	}
	return out;
}

inline Mat operator*(Mat l, Mat r) {
	Mat res(l.n, r.m);
	rep(i, 0, res.n) rep(j, 0, res.m) rep(k, 0, l.m)
		res.arr[i][j] += l.arr[i][k] * r.arr[k][j];
	rep(i, 0, res.n) rep(j, 0, res.m) res.arr[i][j] %= MOD;
	return res;
}

Mat operator^ (const Mat & v, ll u)
{
	Mat res(v.n, v.m, 1);
	for (int i = 62; ~i; i--) {
		res = res * res;
		if (u & (1ll << i)) res = res * v;
	}
	return res;
}

vector<int> state, f[MAXN];
map<vector<int>, int> rf;
int NOW, sz[MAXN];
void build(int g = 0) {
	if (g == c) {
		f[NOW] = state;
		rf[state] = NOW++;
		return;
	}
	rep(i, 0, sz[vec[g]]) {
		state[g] = i;
		build(g + 1);
	}
	return;
}

#ifndef IOI_style
int main() {
	ios::sync_with_stdio(0);
	cin.tie(0);
#ifdef USACO
	freopen("gathering.in", "r", stdin);
	freopen("gathering.out", "w", stdout);
#endif
	cin >> n >> c;
	rep(i, 0, c) {
		char v; int m;
		cin >> v >> m;
		v -= 'A';
		vec.pb(v);
		o[v].pb(m);
	}
	sort(for_all(vec));
	vec.resize(unique(for_all(vec)) - vec.begin());
	for (auto e : vec) {
		sort(for_all(o[e]));
		o[e].resize(unique(for_all(o[e])) - o[e].begin());
		sz[e] = 1;
		for (auto z : o[e]) sz[e] *= z;
	}
	state.resize(vec.size());
	c = vec.size(); build();
	Mat M(NOW, NOW);
	rep(i, 0, NOW) {
		auto v = f[i];
		rep(j, 0, c) {
			v[j] = (v[j] + 1) % sz[vec[j]];
			M.arr[rf[v]][i]++;
			v[j] = (v[j] - 1 + sz[vec[j]]) % sz[vec[j]];
		}
	}
	M = M ^ n;
	ll answer = 0;
	rep(i, 0, NOW) {
		auto v = f[i];
		bool bad = false;
		rep(j, 0, c) {
			bool flag = false;
			for (auto z : o[vec[j]])
				if (v[j] % z == 0) flag = true;
			if (!flag) bad = true;
		}
		if (bad) continue;
		add(answer, M.arr[i][0]);
	}
	cout << answer << endl;
	$;
	return 0;
}
#endif

//typedef Matrix<12345> matrix;
//void _(){
//    ll n,c;
//    cin >> n >> c;
//    vector<pair<char,int> > cond(c);
//    cin >> cond;
//    map<char,int> ways;
//    for(auto _ : cond){
//        char a;
//        int x;
//        tie(a,x) = _;
//        cin >> a >> x;
//        if(!ways.count(a))
//            ways[a] = 1;
//        ways[a] *= x;
//    }
//    map<char,int> index_of;
//    int bm_max = 1;
//    int id = 0;
//    vi sizes;
//    for(auto _ : ways){
//        sizes.pb(_.Y);
//        index_of[_.X] = id++;
//        bm_max *= _.Y;
//    }
//    vvi states;
//    rep(i,0,bm_max-1){
//        int bm = i;
//        vi state;
//        for(auto _ : ways){
//            int t = bm%_.Y;
//            state.pb(t);
//            bm /= _.Y;
//
//        }
//        states.pb(state);
//    }
//    sort(all(states));
//    int m = sz(states);
//    matrix init(m,1),trans(m,m);
//    init[0][0] = 1;
//    vb is_legal(m,0);
//    rep(i,0,m-1){
//        vi tmp = states[i];
//        rep(j,0,sz(tmp)-1){
//            vi _ = tmp;
//            _[j]++;
//            _[j] %= sizes[j];
//            int nxt_index = lower_bound(all(states),_)-states.begin();
//            trans[nxt_index][i] += 1;
//        }
//        set<char> excused;
//        for(auto _ : cond){
//            int id = index_of[_.X];
//            if(tmp[id]%_.Y == 0)
//                excused.insert(_.X);
//        }
//        is_legal[i] = sz(excused) == sz(ways);
//    }
//    matrix ans;
//    if(n == 0)
//        ans = init;
//    else{
//        trans = trans.to_pow(n);
//        ans = trans*init;
//    }
//    ll ret = 0;
//    rep(i,0,m-1)
//        if(is_legal[i])
//            ret = (ret+ans[i][0])%12345;
//    print(ret);
//}
//
#include <map>
#include <set>
#include <iomanip>
#include <algorithm>
#include <cassert>
#include <vector>
#include <utility>
#include <iostream>
#include <string>
#define pb push_back
#define REP_INT(i,l,r) for(int i = l; i <= r; ++i)
#define GET_REP_MACRO(_1,_2,_3,_4,NAME,...) NAME
#define rep(...) GET_REP_MACRO(__VA_ARGS__,REP_ANY,REP_INT)(__VA_ARGS__)
#define all(v) (v).begin(), (v).end()
#define sz(v) ll(v.size())
#define X first
#define Y second
#define T1 template<typename T> static
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<bool> vb;
typedef vector<vl> vvl;
typedef vector<int> vi;
typedef vector<vi> vvi;
T1 ostream& operator<<(ostream& stream, const vector<T>& t);
template <typename F, typename S> static
istream& operator>>(istream& stream, pair<F, S>& t){
    return stream >> t.first >> t.second;
}
T1 istream& read(T, T, istream& = cin);
T1 istream& operator>>(istream& stream, vector<T>& t){
    return read(all(t), stream);
}
T1 istream& read(T b, T e, istream& stream){
    for(T it = b; it != e; ++it)
        stream >> *it;
    return stream;
}
T1 void print(T x, string end = "\n"){
    cout << x << end;
}
template<ll mod = 0>
struct Matrix{
    vvl data;
    Matrix(){
    }
    Matrix(int n, int m){
        data = vvl(n,vl(m));
    }
    Matrix(vvl _data):data(_data){
        for(auto &_ : data)
            for(auto &_ : _){
                if(abs(_) >= mod)
                    _ %= mod;
                if(_ < 0)
                    _ += mod;
            }
    }
    vl &operator[](int row){
        return data[row];
    }
    void operator=(const vvl &_data){
        data = _data;
    }
    Matrix without(int r, int c){
        Matrix ans = *this;
        ans.data.erase(ans.data.begin()+r);
        for(auto &_ : ans.data)
            _.erase(_.begin()+c);
        return ans;
    }
    Matrix operator*(const Matrix &t)const{
        assert(!data.empty());
        assert(!t.data.empty());
        ll n = sz(data), m = sz(t.data[0]), same = sz(t.data);
        assert(sz(data[0]) == same);
        Matrix ans(n,m);
        rep(i,0,n-1)
            rep(j,0,m-1)
                rep(k,0,same-1){
                    ans.data[i][j] += data[i][k]*t.data[k][j];
                    if(mod)
                        ans.data[i][j] %= mod;
                }
        return ans;
    }
    friend ostream& operator<<(ostream &stream, Matrix &t){
        for(int i = 0; i < sz(t.data); ++i){
            if(i)
                stream << '\n';
            for(int j = 0; j < sz(t.data[i]); ++j){
                if(j)
                    stream << ' ';
                stream << t.data[i][j];
            }
        }
        return stream;
    }
    Matrix to_pow(ll p){
        assert(p >= 0);
        Matrix ans;
        Matrix mult = *this;
        for(ll i = 0; (1LL<<i) <= p; ++i){
            if(p&(1LL<<i))
                if(ans.data.empty())
                    ans = mult;
                else
                    ans = ans*mult;
            mult = mult*mult;
        }
        return ans;
    }
};
typedef Matrix<12345> matrix;
void _(){
    ll n,c;
    cin >> n >> c;
    vector<pair<char,int> > cond(c);
    cin >> cond;
    map<char,int> ways;
    for(auto _ : cond){
        char a;
        int x;
        tie(a,x) = _;
        cin >> a >> x;
        if(!ways.count(a))
            ways[a] = 1;
        ways[a] *= x;
    }
    map<char,int> index_of;
    int bm_max = 1;
    int id = 0;
    vi sizes;
    for(auto _ : ways){
        sizes.pb(_.Y);
        index_of[_.X] = id++;
        bm_max *= _.Y;
    }
    vvi states;
    rep(i,0,bm_max-1){
        int bm = i;
        vi state;
        for(auto _ : ways){
            int t = bm%_.Y;
            state.pb(t);
            bm /= _.Y;
        }
        states.pb(state);
    }
    sort(all(states));
    int m = sz(states);
    matrix init(m,1),trans(m,m);
    init[0][0] = 1;
    vb is_legal(m,0);
    rep(i,0,m-1){
        vi tmp = states[i];
        rep(j,0,sz(tmp)-1){
            vi _ = tmp;
            _[j]++;
            _[j] %= sizes[j];
            int nxt_index = lower_bound(all(states),_)-states.begin();
            trans[nxt_index][i] += 1;
        }
        set<char> excused;
        for(auto _ : cond){
            int id = index_of[_.X];
            if(tmp[id]%_.Y == 0)
                excused.insert(_.X);
        }
        is_legal[i] = sz(excused) == sz(ways);
    }
    matrix ans;
    if(n == 0)
        ans = init;
    else{
        trans = trans.to_pow(n);
        ans = trans*init;
    }
    ll ret = 0;
    rep(i,0,m-1)
        if(is_legal[i])
            ret = (ret+ans[i][0])%12345;
    print(ret);
}
int main(){
    ios_base::sync_with_stdio(false);
    cin.tie(nullptr);
    cout << fixed << setprecision(15);
        _();
}

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

typedef vector<vector<int> > Matrix;
typedef long long ll;

const int MOD = 12345;
int add(int a, int b) { return a+b-(a+b>=MOD)*MOD; }
int mult(int a, int b) { return (1LL*a*b)%MOD; }

Matrix make(int a, int b) { return Matrix(a,vector<int>(b)); }
Matrix mult(Matrix a, Matrix b) {
	Matrix res = make(a.size(),b[0].size());
	for (int i=0;i<a.size();i++) {
		for (int j=0;j<b[0].size();j++) {
			for (int k=0;k<a[0].size();k++) {
				res[i][j] = add(res[i][j],mult(a[i][k],b[k][j]));
			}
		}
	}
	return res;
}
Matrix modpow(Matrix x, ll p) {
	Matrix ans = make(x.size(),x.size());
	for (int i=0;i<x.size();i++) ans[i][i] = 1;
	while (p) {
		if (p&1) ans = mult(ans,x);
		p>>=1;
		x = mult(x,x);
	}
	return ans;
}

ll n,m;
set<int> conditions[27];
int lcmd[27];
int good[27][130];
int D = 0;
map<vector<int>,int> mp;
vector<int> states[125];

void getstates(vector<int> v, int cur){
	if(cur==26){
		states[D] = v;
		mp[v] = D;
		D++;
		//cout << v << endl;
		return;
	}
	for(int i=0;i<lcmd[cur];i++){
		v[cur]=i;
		getstates(v, cur+1);
	}
}

int main(){

	cin >> n >> m;
	for(int i=0;i<m;i++){
		char c;int x;
		cin >> c >> x;
		conditions[c-'A'].insert(x);
	}
	for(int i=0;i<26;i++)lcmd[i]=1;
	for(int i=0;i<26;i++)for(auto t:conditions[i])lcmd[i]*=t;
	for(int i=0;i<26;i++){
		good[i][0]=1;
		for(auto t:conditions[i]){
			int cur = t;
			for(int j=0;j<lcmd[i];j+=cur){
				good[i][j]=1;
			}
		}
	}
	vector<int> v(26);
	iota(v.begin(),v.end(),0);
	getstates(v, 0);
	Matrix A = make(D,D);
	for(int i=0;i<D;i++){
		vector<int> v = states[i];
		for(int j=0;j<26;j++)if(!conditions[j].empty()){
			int c = lcmd[j];
			v[j] = (v[j]+1)%c;
			A[i][mp[v]]++;
			v[j] = (v[j]-1+c)%c;
		}
	}

	A = modpow(A, n);
	int ans = 0;
	for(int i=0;i<D;i++){
		vector<int> v = states[i];
		bool flag = true;
		for(int j=0;j<26;j++)if(!good[j][v[j]])flag = false;
		if(flag){
			ans = add(ans, A[0][i]);
		}
	}
	cout << ans << endl;

	return 0;
}

#include <iostream>
#include <cmath>
#include <set>
#include <numeric>
#include <vector>
#include <map>
#include <algorithm>
#include <cstdio>
#include <memory.h>

using namespace std;

#define SZ(a) (int)(a).size()
#define FOR(i, a, b) for(int i=(a), _b(b); i<_b; ++i)
#define FORD(i, b, a) for(int i=(b)-1, _a(a); i>=_a; --i)
#define FILL(a, b) memset(a, b, sizeof(a))
#define SQR(a) ((a)*(a))
#define HASB(a, i) ((a&(1<<i))>0)

typedef long long LL;
typedef pair<int, int> PII;
typedef vector<int> VI;

template<typename T>
void Out(T res)
{
	cout << res << endl;
	exit(0);
}

LL n;
VI T[26], all;
PII pos[26];

int Add(int a, int b, int mod)
{
	a += b;
	if (a >= mod) return a-mod;
	if (a < 0) return a+mod;
	return a;
}

int Mul(int a, int b, int mod)
{
	return (a*b)%mod;
}

VI decode(int state)
{
	VI res;
	FOR(i, 0, SZ(all))
	{
		res.push_back(state%all[i]);
		state /= all[i];
	}
	return res;
}

int code(VI res)
{
	int state = 0, p = 1;
	FOR(i, 0, SZ(all))
	{
		state += res[i]*p;
		p *= all[i];
	}
	return state;
}

const int N = 124;
const int MOD = 12345;
int a[N][N], res[N][N];

void mul(int a[][N], int b[][N], int c[][N])
{
	int res[N][N]; FILL(res, 0);
	FOR(i, 0, N)
		FOR(j, 0, N)
			FOR(k, 0, N)
				res[i][k] = Add(res[i][k], Mul(a[i][j], b[j][k], MOD), MOD);
	FOR(i, 0, N)
		FOR(j, 0, N)
			c[i][j] = res[i][j];
}

int main()
{
#ifdef ALMAG_LOCAL
	freopen("input.txt", "r", stdin);
#else
	//freopen("rating.in", "r", stdin);
	//freopen("rating.out", "w", stdout);
#endif

	int m; cin >> n >> m;

	int ones = 0;
	FOR(i, 0, m)
	{
		string s; int t;
		cin >> s >> t;
		T[s[0]-'A'].push_back(t);
	}

	FOR(i, 0, 26)
	{
		sort(T[i].begin(), T[i].end());
		T[i].erase(unique(T[i].begin(), T[i].end()), T[i].end());
	}

	int len = 0, prev = 0;
	FOR(i, 0, 26)
	{
		len = 0;
		FOR(j, 0, SZ(T[i]))
		{
			if (T[i][j] == 1) ones++;
			else
			{
				len++;
				all.push_back(T[i][j]);
			}
		}
		pos[i] = PII(prev, prev+len);
		prev += len;
	}

	FOR(i, 0, N)
	{
		a[i][i] = ones;
		VI curr = decode(i);
		FOR(j, 0, 26)
		{
			if (!(pos[j].second-pos[j].first)) continue;
			FOR(p, pos[j].first, pos[j].second)
			{
				curr[p] = Add(curr[p], +1, all[p]);
			}
			a[i][code(curr)]++;
			FOR(p, pos[j].first, pos[j].second)
			{
				curr[p] = Add(curr[p], -1, all[p]);
			}
		}
	}

	FOR(i, 0, N)
		res[i][i] = 1;

	for(; n; n>>=1)
	{
		if (n&1)
			mul(res, a, res);
		mul(a, a, a);
	}

	int ans = 0;
	FOR(i, 0, N)
	{
		VI curr = decode(i);
		int k = 1;

		FOR(j, 0, 26)
		{
			if (!(pos[j].second-pos[j].first)) continue;
			k = 0;
			FOR(p, pos[j].first, pos[j].second)
				if (curr[p] == 0) {
					k = 1; break;
				}
			if (!k) break;
		}

		ans = Add(ans, k*res[0][i], MOD);
	}

	cout << ans << endl;

	return 0;
}

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
//#include<iomanip>
//#include<cassert>
#include<set>
using namespace std;
#define maxc 27
#define maxz 125
#define mod 12345
int n,c;
int use; //����num�ı���״̬ѹ��������ֵ
vector<int> ch[maxc];
set<int> chh[maxc];
int base[maxc],f[maxc];
//int dp[maxz][maxz];
bool hash[maxc];
struct Matrix //ģ�µ�zz_1215ѧ���Ĵ��룬�Լ�д��̫������...
{
    int a[maxz][maxz];
    Matrix()
    {
        memset(a,0,sizeof(a));
    }
    void operator *=(const Matrix &y)
    {
        Matrix x;
        for(int i=0;i<use;++i)
            for(int j=0;j<use;++j)
                for(int k=0;k<use;++k)
                {
                    x.a[i][j]+=a[i][k]*y.a[k][j];
                    x.a[i][j]%=mod;
                }
        memcpy(a,x.a,sizeof(x.a));
        return ;
    }
    Matrix pow(long long n)
    {
        Matrix x,y;
        memcpy(y.a,a,sizeof(a));
        for(int i=0;i<use;++i)
            x.a[i][i]=1;
        while(n)
        {
            if(n%2==1)
                x*=y;
            y*=y;
            n>>=1;
        }
        return x;
    }
};
int change(int a,int b)
{
    int ans=0,i,base=1,tmp;
    for(i=0;i<ch[b].size();++i)
    {
//        base*=ch[b][i];
        tmp=a%ch[b][i];
        tmp=(tmp+1)%ch[b][i];
        ans+=tmp*base;
        base*=ch[b][i];
        a/=ch[b][i];
    }
    return ans;
//    return (a+1)%f[b];
}
bool can(int a)
{
    int i,j,tmp,bbase,ttmp;
    bool ans=1;
    for(i=1;i<maxc;++i)
    {
        if(hash[i])
        {
            tmp=a%f[i];
            a/=f[i];
//            bbase=1;
            ans=0;
            for(j=0;j<ch[i].size();++j)
            {
//                bbase*=ch[i][j];
                ttmp=tmp%ch[i][j];
                if(ttmp==0)
                {
                    ans=1;
                    break;
                }
                tmp/=ch[i][j];
            }
            if(ans==0)
                return 0;
        }
    }
    return ans;
}
void work()
{
    Matrix tmp;
    int i,j,tmp1,tmp2,to,ans=0;
    for(i=0;i<use;++i)
    {
        tmp1=i;
        for(j=1;j<maxc;++j)
        {
            if(hash[j])
            {
                tmp2=tmp1%f[j];
                tmp1/=f[j];
//                tmp1=i%base[j-1];
//                tmp2/=base[j];
                to=change(tmp2,j);
//                to=tmp1+to*base[j-1]+tmp2*base[j];
                to=i-tmp2*base[j-1]+to*base[j-1];
                tmp.a[i][to]++;
            }
        }
    }
//    cout<<"inital complete"<<endl;
//    zero.a[0][0]=1;
    tmp=tmp.pow(n);
//    cout<<"quickpow complete"<<endl;
    for(i=0;i<use;++i)
        if(can(i))
            ans=(ans+tmp.a[0][i])%mod;
    cout<<ans<<endl;
}
int main()
{
    int i,j,num;
    set<int>::iterator it;
    char cha;
    while(cin>>n>>c)
    {
        for(i=1;i<maxc;++i)
            ch[i].clear(),chh[i].clear();
        memset(hash,0,sizeof(hash));
        use=1;
        for(i=0;i<c;++i)
        {
            cin>>cha>>num;
//            use*=num;
            chh[cha-'A'+1].insert(num);
//                use*=num;
            hash[cha-'A'+1]=1;
        }
        for(i=1;i<maxc;++i)
        {
            if(hash[i])
                for(it=chh[i].begin();it!=chh[i].end();++it)
                    ch[i].push_back(*it);
        }
        for(i=0;i<maxc;++i)
            base[i]=1,f[i]=1;
        for(i=1;i<maxc;++i)
        {
            for(j=0;j<ch[i].size();++j)
                f[i]*=ch[i][j];
            base[i]=base[i-1]*f[i];
            use*=f[i];
        }
//        cout<<"prepare complete"<<endl;
        work();
    }
    return 0;
}

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

struct matrix
{int a[130][130];
};
struct matrix g,f,e;

struct unit
{int x;
 vector<int> w;
};
struct unit a[30];

long long n;
int m,ans;
int b[30],c[30];
const int mod=12345;

bool cmp(struct unit aa,struct unit bb)
{return aa.x>bb.x;
}

int gcd(int i,int j)
{if(j==0)
    return i;
 else
    return gcd(j,i%j);
}

matrix operator *(matrix aa,matrix bb)
{matrix ret;
 int i,j,k;
 memset(ret.a,0,sizeof(ret.a));
 for(i=0;i<=123;i++)
    for(j=0;j<=123;j++)
    {   for(k=0;k<=123;k++)
        {   ret.a[i][j]=(ret.a[i][j]+aa.a[i][k]*bb.a[k][j]);
            if(k&7==0)
                ret.a[i][j]%=mod;
        }
        ret.a[i][j]%=mod;
    }
 return ret;
}

matrix fpow(long long j)
{matrix ret=e,t;
 t=g;
 while(j>0)
 {  if(j&1) ret=ret*t;
    t=t*t;
    j/=2;
 }
 return ret;
}

int main()
{int i,j,x,s,s1,flag;
 char ch[2];
 for(i=0;i<=123;i++)
    e.a[i][i]=1;
 scanf("%I64d%d",&n,&m);
 for(i=1;i<=m;i++)
 {  scanf("%s%d",ch,&x);
    if(a[ch[0]-64].x==0)
        a[ch[0]-64].x=x;
    else
        a[ch[0]-64].x=a[ch[0]-64].x*x/gcd(a[ch[0]-64].x,x);
    a[ch[0]-64].w.push_back(x);
 }
 sort(a+1,a+26+1,cmp);
 for(i=1;i<=26;i++)
    if(a[i].x==0)
    {   m=i-1;
        break;
    }
 for(i=m;i>=1;i--)
 {  b[i]=1;
    for(j=i+1;j<=m;j++)
        b[i]+=(a[j].x-1)*b[j];
 }
 while(c[0]==0)
 {  s=0;
    for(i=1;i<=m;i++)
        s+=c[i]*b[i];
    for(i=1;i<=m;i++)
    {   if(c[i]==a[i].x-1)
            s1=s-b[i]*(a[i].x-1);
        else
            s1=s+b[i];
        g.a[s][s1]++;
    }
    i=m;
    while(c[i]==a[i].x-1)
    {   c[i]=0;
        i--;
    }
    c[i]++;
 }
 f=fpow(n);
 memset(c,0,sizeof(c));
 while(c[0]==0)
 {  s=0;
    flag=1;
    for(i=1;i<=m;i++)
        s+=c[i]*b[i];
    for(i=1;i<=m;i++)
    {   flag=0;
        for(j=0;j<a[i].w.size();j++)
            if(c[i]%a[i].w[j]==0)
            {   flag=1;
                break;
            }
        if(!flag) break;
    }
    if(flag) ans=(ans+f.a[0][s])%mod;
    i=m;
    while(c[i]==a[i].x-1)
    {   c[i]=0;
        i--;
    }
    c[i]++;
 }
 cout<<ans<<endl;
 return 0;
}

#include <bits/stdc++.h>

#define ll long long
#define ld long double
#define pii pair<int,int>
#define pll pair<ll,ll>
#define pdd pair<ld,ld>
#define ff first
#define ss second
#define pb push_back
#define mp make_pair
#define MAXINT ((~0) ^ (1 << 31))
#define MAXLL ((~0) ^ ((ll)1 << 63))
#define INF ((int)2e9)
#define INFL ((ll)9e18)
#define FOR(i,j,k) for(int i = j; i < k; i++)
#define REP(i,j,k) for(int i = j; i >= k; i--)
#define setmax(i) const int maxn = (int) i;
#define setmod(i) const int MOD = (int) i;
#define all(a) a.begin(),a.end()

//srand (time(NULL));

using namespace std;

setmod(12345);

struct matrix
{
    int num[130][130];
    matrix()
    {
	FOR(i,0,130) FOR(j,0,130) num[i][j] = 0;
    }
} trans;

int sz = 1;

matrix mult(matrix& a, matrix& b)
{
    matrix c;
    FOR(i,0,sz) FOR(j,0,sz) FOR(k,0,sz)
    {
	c.num[i][j] += a.num[i][k]*b.num[k][j];
	c.num[i][j] %= MOD;
    }
    return c;
}

matrix po(matrix& a, int k)
{
    if(k == 1) return a;
    matrix t = po(a, k/2);
    t = mult(t,t);
    if(k&1) t = mult(t,a);
    return t;
}

int n,c;
int r[26];
bool availible[26];
vector<int> mul[26],v;

int pos; //mapping datas
map<vector<int>,int> m;
map<int, vector<int> > rm;

void dfs(vector<int> t)
{
    if(t.size() == 26)
    {
	m[t] = pos;
	rm[pos] = t;
	pos++;

	//FOR(i,0,sz) cout << t[i] << " ";
//	cout << endl;

    }
    else
    {
	t.pb(0);
	FOR(i,0,r[t.size()-1])
	{
	    dfs(t);
	    t.back()++;
	}
    }
}

void ex()
{
    v.resize(sz,0); //making state 1
    vector<int> t;
    t.resize(26);
    FOR(i,0,26) t[i] = 0;

    FOR(i,0,26)
    {
	//FOR(i,0,26) cout << t[i] << " ";
//	cout << endl;
	t[i]++;
	t[i] %= r[i];
	if(availible[i])
	{
	   // FOR(i,0,3) cout << t[i] << " ";
	   // cout << endl;
	    v[m[t]]++;
	}
	t[i]=0;
    }

    int ans = 0;
    FOR(i,0,sz)
    {
	t = rm[i];
	bool isans = true;
	FOR(j,0,26) if(availible[j])
	{
	    bool f = false;
	    FOR(k,0,mul[j].size()) if(t[j] % mul[j][k] == 0) f = true;
	    isans &= f;
	}
//	cout << isans << endl;
	if(isans)
	{
	    ans += v[i];
	    ans %= MOD;
	}
    }
    cout << ans;
    exit(0);
}

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

    cin >> n >> c;
    if(n == 0)
    {
	cout << 1;
	return 0;
    }

   // if(n == 1) ex();

    FOR(i,0,26) r[i] = 1;
    FOR(i,0,c)
    {
	char ch;
	int w;
	cin >> ch >> w;
	availible[ch-'A'] = true; // add availiblity
	r[ch-'A'] *= w/__gcd(w,r[ch-'A']); //find lcm of multi...s
	mul[ch-'A'].pb(w); //add multi...
    }

    FOR(i,0,26) sz *= r[i]; // find size of states

    vector<int> t;
    dfs(t); //fullfill the map

    FOR(i,0,sz) FOR(j,0,26)
    {
	//cout << i << " " << j<< endl;
	t = rm[i];
	t[j] = (t[j] + r[j] - 1) % r[j];
	if(availible[j]) trans.num[i][m[t]]++;
    }

    //cout <<"*" <<endl;
  /*  FOR(i,0,sz)
    {
//	cout << i << endl;
	FOR(j,0,sz) cout << trans.num[i][j] << " ";
	cout << endl;
    }*/

    if(n == 1) ex();

    trans = po(trans,(n-1));

    /*FOR(i,0,sz)
    {
	FOR(j,0,sz) cout << trans.num[i][j] << " ";
	cout << endl;
    }*/

    v.resize(sz,0); //making state 1
    t.resize(26);
    FOR(i,0,26) t[i] = 0;

    FOR(i,0,26)
    {
	//FOR(i,0,26) cout << t[i] << " ";
//	cout << endl;
	t[i]++;
	t[i] %= r[i];
	if(availible[i])
	{
	    //FOR(i,0,3) cout << t[i] << " ";
	   // cout << endl;
	    v[m[t]]++;
	}
	t[i]=0;
    }

   // FOR(i,0,sz) cout << v[i] << " ";
   // cout << endl;

    int ans = 0;
    FOR(i,0,sz)
    {
	t = rm[i];
	bool isans = true;
	FOR(j,0,26) if(availible[j])
	{
	    bool f = false;
	    FOR(k,0,mul[j].size()) if(t[j] % mul[j][k] == 0) f = true;
	    isans &= f;
	}
//	cout << isans << endl;
	if(isans)
	{
	    FOR(j,0,sz)
	    {
		ans += trans.num[i][j] * v[j];
		ans %= MOD;
	    }
	}
    }
    cout << ans;
}

#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <complex>
#include <map>
#include <set>
#include <string>
#include <vector>
using namespace std;

const int MAXNUM = 123, MOD = 12345;

typedef int Mat[MAXNUM][MAXNUM];

Mat base, ret;
bool hash[26][MAXNUM + 1];
vector<int> l[MAXNUM], b;
int ans = 0;
long long n;

void mul(Mat a, Mat b, Mat c, int n) {
  static Mat tmp;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      tmp[i][j] = 0;
      for (int k = 0; k < n; ++k) {
        tmp[i][j] = (tmp[i][j] + b[i][k] * c[k][j]) % MOD;
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      a[i][j] = tmp[i][j];
    }
  }
}

void pow(long long b, int n) {
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      ret[i][j] = i == j;
    }
  }
  while (b) {
    if (b & 1) mul(ret, ret, base, n);
    mul(base, base, base, n);
    b >>= 1;
  }
}

void dfs(int step, int begin, int kind) {
  if (step == 26) {
    if (b.size() & 1) kind = -kind;
    static int x[26], y[26];
    int tot = 1;
    for (size_t i = 0; i < b.size(); ++i) {
      tot *= b[i];
    }
    for (int i = 0; i < tot; ++i) {
      for (int j = 0; j < tot; ++j) {
        base[i][j] = 0;
      }
    }
    for (int i = 0; i < tot; ++i) {
      int t = i;
      for (size_t j = 0; j < b.size(); ++j) {
        x[j] = t % b[j];
        t /= b[j];
      }
      for (size_t j = 0; j < b.size(); ++j) {
        memcpy(y, x, sizeof(x));
        y[j] = (y[j] + 1) % b[j];
        int to = 0;
        for (int k = b.size() - 1; k >= 0; --k) {
          to = to * b[k] + y[k];
        }
        ++base[i][to];
      }
    }
    pow(n, tot);
    ans = (ans + kind * ret[0][0] + MOD) % MOD;
    return;
  }
  if (l[step].size() == 0u) {
    dfs(step + 1, 0, kind);
  } else {
    for (size_t i = begin; i < l[step].size(); ++i) {
      if (begin == 0) {
        b.push_back(l[step][i]);
        dfs(step, i + 1, -kind);
        dfs(step + 1, 0, -kind);
        b.pop_back();
      } else {
        b.back() *= l[step][i];
        dfs(step, i + 1, -kind);
        dfs(step + 1, 0, -kind);
        b.back() /= l[step][i];
      }
    }
  }
}

int main() {
  int m, x;
  char ch;
  scanf("%lld%d", &n, &m);
  for (int i = 0; i < m; ++i) {
    scanf(" %c%d", &ch, &x);
    hash[ch - 'A'][x] = true;
  }
  for (int i = 0; i < 26; ++i) {
    for (int j = 1; j <= MAXNUM; ++j) {
      if (!hash[i][j]) continue;
      l[i].push_back(j);
      for (int k = j + j; k <= MAXNUM; k += j) {
        hash[i][k] = false;
      }
    }
  }
  dfs(0, 0, 1);
  printf("%d\n", ans);
  return 0;
}

#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <array>
#include <algorithm>
#include <utility>
#include <map>
#include <queue>
#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>

#define ll long long
#define ld long double
#define eps 1e-8
#define MOD 12345

#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f

// change if necessary
#define MAXN 1000000

using namespace std;

struct M {
    const static int n = 123;
    ll m[n][n];
    M() { memset(m, 0, sizeof m); }
    M operator*(const M& m2) {
        M res;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int a = 0; a < n; a++) {
                    res.m[i][j] += m[i][a] * m2.m[a][j];
                    if (res.m[i][j] >= MOD) res.m[i][j] %= MOD;
                }
            }
        }
        return res;
    }
    ll* operator[](const int &x) { return m[x]; }
    static M pow(M &m, ll e) {
        M res = I();
        while (e) {
            if (e & 1) res = res * m;
            m = m * m;
            e >>= 1;
        }
        return res;
    }
    static M I() {
        M m;
        for (int i = 0; i < n; i++) m.m[i][i] = 1;
        return m;
    }
};

int n, c;
vector<int> cond[30];
int prod[30];
int prod2[30];
int tot = 1;

int main() {
    cin.tie(0)->sync_with_stdio(0);

    cin >> n >> c;
    for (int i = 0; i < c; i++) {
        char t; int m; cin >> t >> m;
        cond[t - 'A'].push_back(m);
    }

    for (int i = 0; i < 26; i++) {
        if (!cond[i].empty()) {
            prod[i] = tot;
            for (int j : cond[i]) tot *= j;
            prod2[i] = tot;
        }
    }
    M m;
    for (int i = 0; i < tot; i++) {
        for (int j = 0; j < 26; j++) {
            if (prod[j]) {
                int nxt = (i + prod[j]) % prod2[j] + i / prod2[j] * prod2[j];
                m[i][nxt]++;
            }
        }
    }

    m = M::pow(m, n);
    ll ans = 0;
    for (int i = 0; i < tot; i++) {
        bool works = true;
        for (int j = 0; j < 26; j++) {
            if (prod[j]) {
                int val = (i % prod2[j]) / prod[j];
                bool any = false;
                for (int k : cond[j]) {
                    if (val % k == 0) {
                        any = true;
                        break;
                    }
                }
                if (!any) {
                    works = false;
                    break;
                }
            }
        }
        if (works) {
            ans += m[0][i];
            if (ans >= MOD) ans -= MOD;
        }
    }
    cout << ans << '\n';

    return 0;
}

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include <ctime>
//#include <cmath>
#include <vector>
#include <map>
using namespace std;
typedef long long LL;
typedef pair<int,int> pint;
typedef pair<LL,LL> pll;
#define fi first
#define se second
typedef map<int,int> mapint;
typedef vector<int> vint;
typedef vector<vint> vintp;
#define rep(i,j,k) for (int i = (j);i <= (k);i ++)
#define ran2 (rand() % 32000 * 32000 + rand() % 32000)
#define pb push_back
#define mp make_pair

const int mod = 12345;
int n,j,k,l,i,o,p,__t;
LL m;
pint query[100];
string s;
char ch;
void read(int &a){
	for (ch = getchar();(ch < '0' || ch > '9') && (ch != '-');ch = getchar());
	if (ch == '-') a = 0,__t = -1; else a = ch - '0',__t = 1;
	for (ch = getchar();ch >= '0' && ch <= '9';ch = getchar()) a = a * 10 + ch - '0';
	a *= __t;
}

void mul(){

}

int deg[1000],size,ans;
map <vint, int> num;
vint A;
bool char_exist[100];
int Map[200][200],correct[200],F[200][200],ANS[200][200];

void DFS(int P, int s){
	if (P == n + 1){
		if (s == 0){
			num[A] = ++ size;
			return;
		}
		if (s == 1){
			int temp = num[A];
			rep(i, 0, 25) if (char_exist[i]){
				vint B = A;
				rep(j, 1, n)
					if (i == query[j].fi)
						B[j] = (B[j] + 1) % query[j].se;
				Map[temp][num[B]] += 1;
			}
			return;
		}
		if (s == 2){
			bool could = 1;
			rep(i, 0, 25)
				if (char_exist[i] && correct[i] == 0)
					could = 0;
			ans = (ans + could * F[1][num[A]]) % mod;
		}
	}
	rep(i, 0, query[P].se - 1){
		A[P] = i;
		if (i == 0) correct[query[P].fi] ++;
		DFS(P + 1, s);
		if (i == 0) correct[query[P].fi] --;
	}
}

void build_mat(){
	for (int i = 1; i <= n; i ++)
		char_exist[query[i].fi] = 1;
	rep(i, 1, n + 1)
		A.pb(0);
	DFS(1,0);
	DFS(1,1);
}
int temp[200][200];
void quick(){
	rep(i, 1, size) ANS[1][1] = 1;

	for (LL i = 1; i <= m; i *= 2){
		if (m & i){
			memset(temp, 0, sizeof temp);
			rep(i, 1, size)
				rep(j, 1, size)
					rep(k, 1, size)
						temp[i][k] = (temp[i][k] + ANS[i][j] * Map[j][k]) % mod;
			rep(i, 1, size)
				rep(j, 1, size)
					ANS[i][j] = temp[i][j];
		}
		memset(temp, 0, sizeof temp);
			rep(i, 1, size)
				rep(j, 1, size)
					rep(k, 1, size)
						temp[i][k] = (temp[i][k] + Map[i][j] * Map[j][k]) % mod;
			rep(i, 1, size)
				rep(j, 1, size)
					Map[i][j] = temp[i][j];
	}
}

void solve(){
	F[1][1] = 1;
	quick();
	memset(temp, 0, sizeof temp);
	rep(i, 1, 1)
		rep(j, 1, size)
			rep(k, 1, size)
				temp[i][k] = (temp[i][k] + F[i][j] * ANS[j][k]) % mod;
	rep(i, 1, size)
		F[1][i] = temp[1][i];
	DFS(1, 2);
}

int main(){
	cin >> m >> n;
	for (int i = 1; i <= n; i ++){
		cin >> s >> k;
		query[i] = mp(s[0] - 'A', k);
	}
	if (n == 0) {printf("0\n"); return 0;}
	if (m == 0) {printf("1\n"); return 0;}
	build_mat();
	solve();
	cout << ans << endl;
}

#include<cstdio>
#include<cstring>
#include<iostream>
#include<map>
using namespace std;
typedef long long ll;
ll read()
{
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
	return x*f;
}
const int mod=12345;
ll n,c;
int place,a[26];
struct matrix
{
	ll a[125][125];
	matrix(){memset(a,0,sizeof(a));}
}e;
matrix operator *(matrix x,matrix y)
{
	matrix res;
	for(int i=1;i<=place;i++)
	  for(int j=1;j<=place;j++)
		for(int h=1;h<=place;h++)
		  (res.a[i][j]+=x.a[i][h]*y.a[h][j])%=mod;
	return res;
}
matrix power(matrix x,ll y)
{
	matrix res;
	for(int i=1;i<=place;i++)res.a[i][i]=1;
	while(y)
	{
		if(y&1)res=res*x;
		x=x*x;y>>=1;
	}
	return res;
}
struct data
{
	int a[26];
	data(){memset(a,0,sizeof(a));}
	bool operator <(const data&other)const
	{
		for(int i=0;i<26;i++)
		  if(a[i]!=other.a[i])
			return a[i]<other.a[i];
		return 0;
	}
};
map<data,int>hsh;
void dfs(int step,data now)
{
	if(step==26)
	{
		hsh[now]=++place;
		return;
	}
	if(a[step]==0)dfs(step+1,now);
	for(int i=0;i<a[step];i++)
	{
		now.a[step]=i;
		dfs(step+1,now);
	}
}
int main()
{
	n=read(),c=read();
	for(int i=1;i<=c;i++)
	{
		char x;scanf("%c",&x);
		int y=read(),z=x-'A';
		if(a[z]==0||a[z]>y)a[z]=y;
	}
	if(n==0){printf("1\n");return 0;}
	if(c==0){printf("0\n");return 0;}
	data st;
	dfs(0,st);
	for(map<data,int>::iterator it=hsh.begin();it!=hsh.end();it++)
	{
		data x=it->first;int y=it->second;
		for(int i=0;i<26;i++)if(a[i])
		{
			int t=x.a[i];
			x.a[i]++;x.a[i]%=a[i];
			e.a[hsh[x]][y]++;
			x.a[i]=t;
		}
	}
	e=power(e,n);
	cout<<e.a[1][1]<<endl;
	return 0;
}

#include <bits/stdc++.h>
#define endl '\n'

using namespace std;
const int MAXN = (1 << 20);
const int mod = (int)12345;
const int64_t inf = (int64_t)1e16 + 42;

template<class T>
struct matrix
{
	int n;
	vector<vector<T> > t;

	matrix(int _n, T val) {n = _n; t.assign(n, vector<T>(n, val)); }
	matrix(int _n) {n = _n; t.assign(n, vector<T>(n, 0)); }
    matrix() { n = 0; t.clear(); }

	matrix operator * (matrix b)
	{
		matrix c = matrix(n, 0);
		for(int i = 0; i < n; i++)
			for(int k = 0; k < n; k++)
				for(int j = 0; j < n; j++)
					c.t[i][j] = (c.t[i][j] + t[i][k] * b.t[k][j]) % mod;
		return c;
	}

	vector<T> operator * (vector<T> b)
	{
		vector<T> c = vector<T>(n, 0);
		for(int i = 0; i < n; i++)
			for(int j = 0; j < n; j++)
                c[i] = (c[i] + t[i][j] * b[j]) % mod;

		return c;
	}

	matrix<T> operator ^ (matrix<T> b)
	{
		matrix<T> c = matrix(n, inf);
		for(int i = 0; i < n; i++)
			for(int k = 0; k < n; k++)
				for(int j = 0; j < n; j++)
					c.t[i][j] = min(c.t[i][j], t[i][k] + b.t[k][j]);
		return c;
	}

	matrix<T> operator + (matrix<T> b)
	{
		matrix<T> c = matrix<T>(n);
		for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                c.t[i][j] =  (t[i][j] + b.t[i][j]) % mod;

		return c;
	}

	matrix<T> operator - (matrix<T> b)
	{
		matrix<T> c = matrix<T>(n);
		for(int i = 0; i < n; i++)
            for(int j = 0; j < n; j++)
                c.t[i][j] = (t[i][j] - b.t[i][j] + mod) % mod;

		return c;
	}

	matrix operator & (matrix b)
	{
		matrix<T> c = matrix<T>(n, -inf);
		for(int i = 0; i < n; i++)
			for(int k = 0; k < n; k++)
				for(int j = 0; j < n; j++)
					c.t[i][j] = max(c.t[i][j], t[i][k] + b.t[k][j]);

		return c;
	}
};

template<class T>
matrix<T> pow_min(matrix<T> base, int64_t p)
{
	if(p == 1) return base;

	if(p % 2ll == 0ll)
	{
		matrix<T> d = pow_min(base, p / 2ll);
		return d ^ d;
	}

	return base ^ pow_min(base, p - 1);
}

template<class T>
matrix<T> pow(matrix<T> base, int64_t p)
{
	if(p == 1) return base;

	if(p % 2ll == 0ll)
	{
		matrix<T> d = pow(base, p / 2ll);
		return d * d;
	}

	return base * pow(base, p - 1);
}

template<class T>
void print(matrix<T> mat)
{
	for(int i = 0; i < mat.n; i++)
		for(int j = 0; j < mat.n; j++)
			if(mat.t[i][j] < inf) cout << mat.t[i][j] << " \n"[j == mat.n - 1];
			else cout << "inf" << " \n"[j == mat.n - 1];

	cout << endl;
}

int64_t n, c;
vector<int> li[1 << 8];
int prod[1 << 8];

void read()
{
    for(char let = 'A'; let <= 'Z'; let++) prod[let] = -1;

    cin >> n >> c;
    for(int i = 0; i < c; i++)
    {
        char let;
        cin >> let;
        int cnt;
        cin >> cnt;

        if(prod[let] == -1) prod[let] = 1;
        prod[let] *= cnt;
        li[let].push_back(cnt);
    }
}

int sz = 1;

void solve()
{
    vector<char> pos;
    for(int i = 'A'; i <= 'Z'; i++)
        if(prod[i] != -1) sz *= prod[i], pos.push_back(i);

    matrix<int64_t> base = matrix<int64_t>(sz);
    vector<int64_t> vec = vector<int64_t>(sz, 0);
    vec[0] = 1;

    for(int state = 0; state < sz; state++)
    {
        int pw = 1;
        for(char let: pos)
        {
            int cc = ((state / pw) % prod[let]), nc = (((state / pw) % prod[let]) + prod[let] - 1) % prod[let];
            base.t[state][state - cc * pw + nc * pw] = 1;
            pw *= prod[let];
        }
    }

    if(n != 0)
    {
        base = pow(base, n);
        vec = base * vec;
    }

    int64_t ans = 0;
    for(int state = 0; state < sz; state++)
    {
        int pw = 1, ok = 1;
        for(char let: pos)
        {
            int cc = ((state / pw) % prod[let]), cok = 0;
            for(int x: li[let]) if(cc % x == 0) cok = 1;
            ok &= cok;
            pw *= prod[let];
        }

        ans = (ans + ok * vec[state]) % mod;
    }

    cout << ans << endl;
}

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

	read();
	solve();
	return 0;
}

#include <cstdio>
#include <cstring>

#include <vector>
#include <algorithm>

using namespace std;
typedef long long llint;

const llint mod = 12345;

llint N; int C;
char c; int mu;
int tot;

int p[ 26 ];
int lcm[ 26 ];
vector< int > d[ 26 ];

inline void unpack( int rank ) {
  for( int i = 0; i < 26; ++i ) {
    p[i] = rank % lcm[i];
    rank /= lcm[i];
  }
}

inline int repack() {
  int ret = p[25];

  for( int i = 24; i >= 0; --i )
    ret = ret * lcm[i] + ( p[i] % lcm[i] );

  return ret;
}

int m[ 124 ][ 124 ];
int r[ 124 ][ 124 ];
int t[ 124 ][ 124 ];

inline void mult( int a[124][124], int b[124][124] ) {
  memset( t, 0, sizeof t );

  for( int i = 0; i < tot; ++i )
    for( int j = 0; j < tot; ++j )
      for( int k = 0; k < tot; ++k )
	t[i][j] = (int)( ( (llint)t[i][j] + (llint)a[i][k] * (llint)b[k][j] ) % mod );

  memcpy( a, t, sizeof t );
}

int main( void )
{
  scanf( "%I64d%d", &N, &C );

  if( N == 0 ) {
    puts( "1" );
    return 0;
  }

  for( int i = 0; i < C; ++i ) {
    scanf( " %c%d", &c, &mu );
    d[c-'A'].push_back( mu );
  }

  tot = 1;

  for( int i = 0; i < 26; ++i ) {
    lcm[i] = 1;

    for( int j = 0; j < d[i].size(); ++j )
      lcm[i] = ( lcm[i] / __gcd( lcm[i], d[i][j] ) ) * d[i][j];

    tot *= lcm[i];
  }

  for( int i = 0; i < tot; ++i ) {
    unpack( i );

    for( int j = 0; j < 26; ++j ) {
      if( d[j].empty() ) continue;
      ++p[j];
      ++m[repack()][i];
      --p[j];
    }

    r[i][i] = 1;
  }

  for( int i = 0; ( 1LL << i ) <= N; ++i ) {
    if( ( ( N >> i )&1 ) == 1 ) mult( r, m );
    mult( m, m );
  }

  llint Sol = 0;

  for( int i = 0; i < tot; ++i ) {
    unpack( i );

    bool good = 1;
    for( int j = 0; j < 26; ++j ) {
      if( d[j].empty() ) continue;
      bool ok = 0;

      for( int k = 0; k < d[j].size(); ++k )
	if( p[j] % d[j][k] == 0 ) ok = 1;

      good = good && ok;
    }

    if( good ) Sol = ( Sol + r[i][0] ) % mod;
  }

  printf( "%d\n", (int)Sol );

  return 0;
}

#include <map>
#include <set>
#include <cmath>
#include <stack>
#include <queue>
#include <string>
#include <vector>
#include <fstream>
#include <sstream>
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <unistd.h>
#include  <sys/time.h>
using namespace std;
#define li		long long int
#define rep(i,to)	for(li i=0;i<((li)to);i++)
#define pb		push_back
#define sz(v)		((li)v.size())

//	TYPE
//	mod
//	p.180

#define TYPE li
#define mat vector<vector<TYPE> >
#define MOD 12345ll
#define MAX 1005

mat mul(mat a,mat b){
	mat res(sz(a),vector<TYPE>(sz(b[0]),0));
	rep(i,sz(a))rep(j,sz(b[0]))rep(k,sz(a[0])) res[i][j]=(res[i][j]+a[i][k]*b[k][j])%MOD;
	return res;
}
mat pow(mat a,li n){
	mat res(sz(a),vector<TYPE>(sz(a[0]),0));
	rep(i,sz(a)) res[i][i]=1;
	while(n){
		if(n%2) res=mul(res,a);
		a=mul(a,a);
		n/=2;
	}
	return res;
}

int main(){
	li n,c,sum[26],type[MAX],mods[MAX],all=1;
	vector<li> have,pos,index;
	cin>>n>>c;
	rep(i,26) sum[i]=1;
	rep(i,c){
		string str;
		cin>>str>>mods[i];
		type[i]=str[0]-'A';
		sum[type[i]]*=mods[i];
		all*=mods[i];
		if(1<mods[i]) have.pb(i);
	}
	mat m(all,vector<TYPE>(all,0));
	pos.pb(1);
	rep(i,26)if(sum[i]!=1) index.pb(i);
	rep(i,sz(index)) pos.pb(pos.back()*sum[index[i]]);
	rep(i,all){
		m[i][i]=(m[i][i]+c-sz(have)+MOD)%MOD;
		rep(j,sz(index)){
			li now=(i%pos[j+1])/pos[j];
			li tmp=i-now*pos[j];
			now=(now+1)%sum[index[j]];
			tmp+=now*pos[j];
			m[i][tmp]=(m[i][tmp]+1)%MOD;
		}
	}
	li res=0;
	m=pow(m,n);
	li exist[26];
	rep(i,26) exist[i]=false;
	rep(i,c) exist[type[i]]=true;
	rep(i,c)if(mods[i]==1) exist[type[i]]=false;
	rep(i,all){
		li bad[26];
		rep(j,26) bad[j]=exist[j];
		rep(j,sz(index)){
			li now=(i%pos[j+1])/pos[j];
			rep(k,c)if(type[k]==index[j] && now%mods[k]==0) bad[index[j]]=false;
		}
		li ok=true;
		rep(j,26)if(bad[j]) ok=false;
		if(ok) res=(res+m[0][i])%MOD;
	}
	cout<<res<<endl;
}

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<vector>
#define mod 12345
#define maxc 1010
#define maxn 150
using namespace std;
typedef long long LL;
struct Matrix
{
    int digit[maxn][maxn],n,m;
    friend Matrix operator * (const Matrix &a,const Matrix &b)
    {
        static Matrix c;
        memset(c.digit,0,sizeof(c.digit));
        c.n=a.n,c.m=b.m;
        for(int i=0;i<c.n;i++)
            for(int j=0;j<c.m;j++)
                for(int k=0;k<a.m;k++)
                    c.digit[i][j]=(c.digit[i][j]+a.digit[i][k]*b.digit[k][j])%mod;
        return c;
    }
}square,ans;
LL m;
int n,c[maxc],seq[maxc];
vector<int> to[30];
int N,sum[maxc];
Matrix power(Matrix p,LL n)
{
    Matrix ans;
    ans.n=p.n,ans.m=p.m;
    for(int i=0;i<ans.n;i++)
        for(int j=0;j<ans.n;j++)
            ans.digit[i][j]=(i==j);
    for(;n;n>>=1,p=p*p)
        if(n&1)
            ans=ans*p;
    return ans;
}
void read()
{
    cin>>m>>n;
    char str[10];
    for(int i=1;i<=n;i++)
    {
        scanf("%s %d",str+1,&c[i]);
        to[str[1]-'A'+1].push_back(i);
        N*=c[i];
    }
    sum[n]=1;
    for(int i=n-1;i>=1;i--)
        sum[i]=sum[i+1]*c[i+1];
    N=sum[1]*c[1];
    square.n=N,square.m=N;
}
int hash()
{
    int total=0;
    for(int i=1;i<=n;i++)
        total=total+seq[i]*sum[i];
    return total;
}
void tran()
{
    int x=hash();
    for(int i=1;i<=26;i++)
        if(to[i].size())
        {
            for(int j=0;j<to[i].size();j++)
                seq[to[i][j]]=(seq[to[i][j]]+1)%c[to[i][j]];
            int y=hash();
            square.digit[x][y]++;
            for(int j=0;j<to[i].size();j++)
                seq[to[i][j]]=(seq[to[i][j]]-1+c[to[i][j]])%c[to[i][j]];
        }
}
void DFS(int p)
{
    if(p>n)
    {
        tran();
        return ;
    }
    for(int i=0;i<c[p];i++)
    {
        seq[p]=i;
        DFS(p+1);
    }
}
LL work()
{
    ans.n=1,ans.m=N;
    ans.digit[0][0]=1;
    ans=ans*power(square,m);
    LL total=0;
    for(int i=0;i<N;i++)
    {
        int s=i,tot=0;
        for(int j=1;j<=n;j++)
        {
            seq[j]=s/sum[j];
            s%=sum[j];
        }
        for(int j=1;j<=26;j++)
        {
            if(to[j].size()==0)
                tot++;
            else
            {
                for(int k=0;k<to[j].size();j++)
                    if(seq[to[j][k]]==0)
                    {
                        tot++;
                        break;
                    }
            }
        }
        if(tot==26)
            total=(total+ans.digit[0][i]);
    }
    return total;
}
int main()
{
    read();
    DFS(1);
    cout<<work()<<endl;
    return 0;
}

#include <stdio.h>
#include <string.h>
const int MOD = 12345;
int cnt,c;
int ok[200];
int wei[30],tnum[30],use[100];
char x[1010],Num[1010],map[1010];
int total[1010],thash[100];
int ans[210][210],num[210][210],tans[210],temp[210];
int tuse[30];
int hash()
{
    int num=0;
    for (int i=cnt-1;i>=0;i--)
        num=num*wei[i+1]+tnum[i];
    return num;
}
void antihash(int state)
{
    for (int i=cnt-1;i>=0;i--)
    {
        tnum[i]=state/wei[i];
        state-=tnum[i]*wei[i];
    }
}
bool judge()
{
    memset(tuse,0,sizeof(tuse));
    for (int i=0;i<c;i++)
        if (tnum[thash[x[i]-'A']]%Num[i]==0) tuse[x[i]-'A']=1;
    for (int i=0;i<cnt;i++)
        if (tuse[map[i]]!=1) return false;
    return true;
}
int tmp[210][210];
void multi(int ans[210][210],int num[210][210])
{
    memset(tmp,0,sizeof(tmp));
    for (int i=0;i<wei[cnt];i++)
        for (int j=0;j<wei[cnt];j++)
            for (int k=0;k<wei[cnt];k++)
            {
                tmp[i][j]+=ans[i][k]*num[k][j];
                tmp[i][j]%=MOD;
            }
    for (int i=0;i<wei[cnt];i++)
        for (int j=0;j<wei[cnt];j++)
            ans[i][j]=tmp[i][j];
}
int main()
{
    long long n;
    while (scanf("%I64d%d",&n,&c)==2)
    {
        memset(use,0,sizeof(use));
        for (int i=0;i<26;i++)
            total[i]=1;
        for (int i=0;i<c;i++)
        {
            scanf(" %c%d",&x[i],&Num[i]);
            use[x[i]-'A']=1;
            total[x[i]-'A']*=Num[i];
        }
        cnt=0;
        int now=1;
        for (int i=0;i<26;i++)
        {
            if (!use[i]) continue;
            wei[cnt]=now;
            map[cnt]=i;
            thash[i]=cnt;
            now*=total[i];
            cnt++;
        }
        wei[cnt]=now;
        memset(ans,0,sizeof(ans));
        for (int i=0;i<wei[cnt];i++)
            ans[i][i]=1;
        memset(num,0,sizeof(num));
        memset(ok,0,sizeof(ok));
        for (int i=0;i<wei[cnt];i++)
        {
            antihash(i);
            if (judge()) ok[i]=true;
            for (int j=0;j<cnt;j++)
            {
                int temp=tnum[j];
                tnum[j]+=total[map[j]]-1;
                tnum[j]%=total[map[j]];
                int next=hash();
                num[next][i]=1;
                tnum[j]=temp;
            }
        }
        while (n!=0)
        {
            if (n%2==1) multi(ans,num);
            multi(num,num);
            n=n/2;
        }
        memset(tans,0,sizeof(tans));
        tans[0]=1;
        memset(temp,0,sizeof(temp));
        for (int j=0;j<wei[cnt];j++)
            for (int k=0;k<wei[cnt];k++)
            {
                temp[j]+=tans[k]*ans[k][j];
                temp[j]%=MOD;
            }
        int ans=0;
        for (int i=0;i<wei[cnt];i++)
            if (ok[i])
            {
                ans+=temp[i];
                ans%=MOD;
            }
        printf("%d\n",ans);
    }
    return 0;
}

#include<cstdio>
#include<cstring>
#include<iostream>

#define nn 210
#define mm 1010
#define Mod 12345
using namespace std;

char c[mm];
int h[nn],ck[nn],d[mm];long long l;
int st[nn],p[mm],tr[nn][nn],rs[nn][nn],n,m,N,ans;

inline void Get_arr(int a){
	for (int i=m;i>=1;i--) st[i]=a/p[i],a%=p[i];
}
inline int Get_id(int *a){
	int rs=0;
	for (int i=1;i<=m;i++) rs+=a[i]*p[i];
	return(rs);
}
inline void Get_tran(){
	p[1]=1;
	for (int i=2;i<=m;i++) p[i]=p[i-1]*d[i-1];
	N=p[m]*d[m];

	for (int i=0;i<N;i++){
		for (int j=0;j<26;j++) if(h[j]){
			Get_arr(i);
			for (int k=1;k<=m;k++) if(c[k]-'A'==j) st[k]=(st[k]+1)%d[k];
			tr[i][Get_id(st)]++;
		}
	}
}

int a[nn],b[nn][nn];
inline void Pow(){
	for (int i=0;i<N;i++) rs[i][i]=1;
	while (l){
		if (l&1){
			for (int i=0;i<N;i++)
			for (int j=0;j<N;j++) b[i][j]=rs[i][j],rs[i][j]=0;
			for (int k=0;k<N;k++)
			for (int i=0;i<N;i++)
			for (int j=0;j<N;j++) rs[i][j]=(rs[i][j]+b[i][k]*tr[k][j]%Mod)%Mod;
		}
		for (int i=0;i<N;i++)
		for (int j=0;j<N;j++) b[i][j]=tr[i][j],tr[i][j]=0;
		for (int k=0;k<N;k++)
		for (int i=0;i<N;i++)
		for (int j=0;j<N;j++) tr[i][j]=(tr[i][j]+b[i][k]*b[k][j]%Mod)%Mod;
		l/=2ll;
	}
}

int main()
{
	scanf("%I64d%d",&l,&m);
	for (int i=1;i<=m;i++){
		c[i]=getchar();
		while ('A'>c[i]||c[i]>'Z') c[i]=getchar();
		scanf("%d",&d[i]);h[c[i]-'A']=1;
	}

	Get_tran();
	Pow();

	for (int i=0;i<N;i++){
		Get_arr(i);
		bool jd=1;
		memset(ck,0,sizeof(ck));
		for (int j=1;j<=m;j++) if(!st[j]) ck[c[j]-'A']=1;
		for (int j=0;j<26;j++) if(h[j]&&!ck[j]) jd=0;
		if (jd) ans=(ans+rs[0][i])%Mod;
	}
	printf("%d\n",ans);
}

/*
 * 2011-08-23  Martin  <Martin@Martin-desktop>

 *
 */
#include <algorithm>
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>

using namespace std;

#define tr(i, x) for (typeof(x.begin()) i = x.begin(); i != x.end(); ++ i)
#define rep(i, n) for (int i = 0; i < n; ++ i)
#define pii pair <int, int>
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define ll long long

#define CharSet 26
#define Mod 12345

class Matrix: public vector < vector <int> >
{
	private:
		Matrix(int n, vector <int> a)
		{
			this->clear();
			rep (i, n)
				pb(a);
		}
	public:
		Matrix()
		{
			this->clear();
		}
		Matrix(int n, int m)
		{
			this->clear();
			*this = Zero(n, m);
		}
		Matrix Zero(int n, int m)
		{
			return Matrix (n, vector <int> (m, 0));
		}
		Matrix One(int n)
		{
			Matrix res(n, n);
			rep (i, n)
				res[i][i] = 1;
			return res;
		}
		Matrix operator * (const Matrix &b)
		{
			Matrix c;
			if (rows() == b.lines())
			{
				int u = lines();
				int v = rows();
				int w = b.rows();
				c = Zero(u, w);
				rep (i, u)
					rep (j, v)
						rep (k, w)
						{
							c[i][k] += (*this)[i][j] * b[j][k];
							c[i][k] %= Mod;
						}
			}
			else
				cerr << "error occurred at " << __LINE__ << endl;
			return c;
		}
		Matrix pow(unsigned ll n)
		{
			Matrix res;
			if (lines() == rows())
			{
				int l = lines();
				res = res.One(l);
				Matrix tmp(*this);
				for (int i = 0; n >> i; ++ i)
				{
					if (n & (1ULL << i))
						res = res * tmp;
					tmp = tmp * tmp;
				}
			}
			else
				cerr << "error occurred at " << __LINE__ << endl;
			return res;
		}
		size_type lines() const
		{
			return size();
		}
		size_type rows() const
		{
			return (size() == 0) ? 0 : (*this)[0].size();
		}
};

ll N;
int C;
bool Appear[CharSet];

int main()
{
	cin >> N >> C;
	fill(Appear, Appear + CharSet, 0);
	vector <pii> cd;
	cd.clear();
	rep (i, C)
	{
		char Ch;
		int t;
		cin >> Ch >> t;
		Appear[Ch - 'A'] = 1;
		if (t != 1)
			cd.pb(mp(Ch - 'A', t));
	}
	vector <int> pd;
	pd.clear();
	int cds = cd.size();
	pd.pb(1);
	rep (i, cds)
		pd.pb(pd.back() * cd[i].y);
	int matsize = pd.back();
	Matrix mat(matsize, matsize);
	rep (i, matsize)
	{
		int target = i;
		rep (ch, 26)
			if (Appear[ch])
			{
				rep (k, cds)
					if (cd[k].x == ch)
					{
						if ((target % pd[k + 1]) / pd[k] == cd[k].y - 1)
							target -= (cd[k].y - 1) * pd[k];
						else
							target += pd[k];
					}
				++ mat[i][target];
			}
	}
	mat = mat.pow(N);
	ll ans = 0;
	rep (i, matsize)
	{
		bool Flag = 1;
		rep (ch, 26)
			if (Appear[ch])
			{
				bool Satisfy = 0;
				bool Exist = 0;
				rep (k, cds)
					if (cd[k].x == ch)
					{
						Exist = 1;
						if ((i % pd[k + 1]) / pd[k] == 0)
							Satisfy = 1;
					}
				if (Exist && !Satisfy)
				{
					Flag = 0;
					break;
				}
			}
		if (Flag)
			ans = (ans + mat[0][i]) % Mod;
	}
	cout << ans << endl;
	return 0;
}

#include <stdio.h>
#include <ctype.h>
#include <iostream>
#include <math.h>
#include <string.h>
#include <algorithm>
#include <stdlib.h>
#include <time.h>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <vector>
#include <utility>

//#define M_PI 3.141592653589793238462643
#define eps 1e-8
#define inf ((int)1e9)
#define pb push_back
#define mp make_pair
#define mod (12345)

using namespace std;

bool operator < (pair <long long, int> i, pair <long long, int> j)
{
  if (i.first!=j.first)
    return i.first<j.first;
  return i.second<j.second;
}

bool A[26][124];
int res;
vector <int> B[26];
int P[26];
map <pair <long long, int>, int > Hash;
int e, Q[26], mm=1, Z[26];
int Conv[123][26];

int solve (long long n, int v)
{
  if (Hash.count(mp(n,v))==0)
  {
    int tmp ,tmp2, i, j;
    Hash[mp(n,v)]=0;
    if (n==1)
    {
      //cerr<<"!!!! "<<v<<endl;
      for (tmp=0, tmp2=0, i=0; i<e; i++)
      {
        if (Conv[v][i]>1)
          return 0;
        if (Conv[v][i]==1 || Q[i]==1)
          tmp++;
        if (Conv[v][i]==1)
          tmp2++;
      }
      //cerr<<tmp<<" "<<tmp2<<endl;
      if (tmp2>1)
        return 0;
      if (tmp==0)
        return 0;
      if (tmp2==1)
      {
        Hash[mp(n,v)]=1;
        return 1;
      }
      Hash[mp(n,v)]=tmp;
      return tmp;
    }
    for (i=0; i<mm; i++)
    {
      //cerr<<i<<endl;
      tmp=0;
      for (j=e-1; j>=0; j--)
      {
        //cerr<<j<<" "<<tmp<<" "<<Q[j]<<endl;
        tmp*=Q[j];
        tmp+=(Conv[v][j]-Conv[i][j]+Q[j])%Q[j];
      }
      //cerr<<tmp<<endl;
      Hash[mp(n,v)]=(Hash[mp(n,v)]+solve(n/2,i)*solve(n-(n/2),tmp))%mod;
    }
  }
  //cerr<<n<<" "<<v<<" "<<Hash[mp(n,v)]<<endl;
  return Hash[mp(n,v)];
}

int main()
{
  int n, c, tmp, i, j, k;
  bool fl, fl2;
  char tmpc;
  //freopen(".in", "r", stdin);
  //freopen(".out", "w", stdout);
  scanf("%I64d%d", &n, &c);
  if (n==0)
  {
    printf("1\n");
    return 0;
  }
  if (c==0)
  {
    printf("0\n");
    return 0;
  }
  for (i=0; i<c; i++)
  {
    scanf(" %c%d", &tmpc, &tmp);
    A[(int)(tmpc-'A')][tmp]=1;
  }
  for (i=0; i<26; i++)
    for (P[i]=1, j=0; j<124; j++)
      if (A[i][j])
        B[i].pb(j), P[i]*=j;
  for (i=0; i<26; i++)
    if (B[i].size()!=0)
      Q[e]=P[i], mm*=P[i], Z[e]=i, e++;
  for (i=0; i<mm; i++)
  {
    j=i;
    for (k=0; k<e; k++)
      Conv[i][k]=j%Q[k],  j/=Q[k];
  }
  for (i=0; i<mm; i++)
  {
    for (fl=1, j=0; j<e; j++)
    {
      for (fl2=1, k=0; k<(int)B[Z[j]].size(); k++)
        if (Conv[i][j]%B[Z[j]][k]==0)
          fl2=0;
      if (fl2)
        fl=0;
    }
    if (fl)
      res=(res+solve(n,i))%mod;
  }
  //cerr<<Q[0]<<" "<<Q[1]<<endl;
  //cerr<<mm<<" "<<e<<" "<<Z[0]<<" "<<Z[1]<<endl;
  /*for (i=0; i<mm; i++)
  {
    for (j=0; j<e; j++)
      printf("%d ", Conv[i][j]);
    printf("\n");
  }  */
  printf("%d\n", res);
  return 0;
}

// 矩乘 DP
// 行列の積 動的計画法

#include<cstdio>
#include<algorithm>

void Get(int &T)
{
	char C;bool F=0;
	for(;C=getchar(),C<'0'||C>'9';)if(C=='-')F=1;
	for(T=C-'0';C=getchar(),C>='0'&&C<='9';T=T*10+C-'0');
	F&&(T=-T);
}

void Get(long long &T)
{
	char C;bool F=0;
	for(;C=getchar(),C<'0'||C>'9';)if(C=='-')F=1;
	for(T=C-'0';C=getchar(),C>='0'&&C<='9';T=T*10+C-'0');
	F&&(T=-T);
}

void Get(char &C)
{
	for(;C=getchar(),C<'A'||C>'Z';);
}

long long N;
int M;
char Type[1005];
int T[1005];
int Base[1005];

bool Visited[255];
bool Cover[255];

void Init()
{
	Get(N);Get(M);
	Base[1]=1;
	int i=1;
	for(int k=1;k<=M;k++)
	{
		Get(Type[i]);Get(T[i]);
		Visited[Type[i]]=1;
		Base[i+1]=Base[i]*T[i];
		if(T[i]!=1) i++;
	}
	i--;
	M=i;
}

int K[1005];

void Debug(int X)
{
	for(int k=M;k>=1;k--)
	{
			printf("%d ",X/Base[k]);
			X%=Base[k];
	}
	puts("");
}

long long A[155][155];
long long B[155][155];

long long Z[155][155];

#define Mod (12345)

void Mul(long long X[][155],long long Y[][155],int N,int M,int K)
{
	for(int i=0;i<N;i++)
		for(int j=0;j<M;j++)
		{
			Z[i][j]=0;
			for(int k=0;k<K;k++)
				(Z[i][j]+=X[i][k]*Y[k][j])%=Mod;
		}

	for(int i=0;i<N;i++)
		for(int j=0;j<M;j++)
			X[i][j]=Z[i][j];
}

long long Ans;

void Work()
{
	for(int i=0;i<Base[M+1];i++)
	{
		for(int k=M,X=i;k>=1;k--)
		{
			K[k]=X/Base[k];
			X%=Base[k];
		}

		for(int j='A';j<='Z';j++)
			if(Visited[j])
			{
				int NewID=0;

				for(int k=M;k>=1;k--)
					if(Type[k]==j)
					{
						NewID+=((K[k]+1)%T[k])*Base[k];
					}
					else
					{
						NewID+=(K[k])*Base[k];
					}

				B[i][NewID]++;
			}
	}

	A[0][0]=1;

	for(;N;N>>=1)
	{
		if(N&1) Mul(A,B,1,Base[M+1],Base[M+1]);
		Mul(B,B,Base[M+1],Base[M+1],Base[M+1]);
	}

	for(int i=0;i<Base[M+1];i++)
	{
		for(int k=M;k>=1;k--)
		{
			Cover[Type[k]]=0;
		}

		for(int k=M,X=i;k>=1;k--)
		{
			K[k]=X/Base[k];
			X%=Base[k];

			if(K[k]==0) Cover[Type[k]]=1;
		}

		bool All=1;

		for(int k=M;k>=1;k--)
		{
			if(Cover[Type[k]]==0)
				All=0;
		}

		if(All)
		{
			(Ans+=A[0][i])%=Mod;
		}

	}
}

void Output()
{
	printf("%I64d\n",Ans);
}

int main()
{
	Init();
	Work();
	Output();
	return 0;
}

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <vector>
#include <map>
using namespace std;
const int MAXN = 1000;
const int MAXM = 123;
const int MOD = 12345;
int d_mul;
struct Matrix{
    int a[MAXM+5][MAXM+5];
    Matrix(int d=0){
        memset(a, 0, sizeof a);
        for(int i=1;i<=d_mul;i++)
            a[i][i] = d;
    }
    Matrix operator*(const Matrix& rhs)const{
        Matrix ret;
        for(int i=1;i<=d_mul;i++){
            for(int j=1;j<=d_mul;j++){
                for(int k=1;k<=d_mul;k++){
                    ret.a[i][j] += a[i][k]*rhs.a[k][j]%MOD;
                    ret.a[i][j] %= MOD;
                }
            }
        }
        return ret;
    }
};
Matrix mpow(Matrix a, long long b){
    Matrix ret(1);
    while(b){
        if(b&1)
            ret=ret*a;
        a=a*a;
        b>>=1;
    }
    return ret;
}
pair<char, int> lim[MAXN+10];
int c, idcnt;
map<vector<int>, int> id;
vector<int> rid[MAXM+10];
void dfs(int u, vector<int> cur){
    if(u > c){
        ++idcnt;
        id[cur] = idcnt;
        rid[idcnt] = cur;
        return ;
    }
    for(int j=0;j<lim[u].second;j++){
        vector<int> nex = cur;
        nex.push_back(j);
        dfs(u+1, nex);
    }
}
inline bool check(register int id){
    for(int i=1;i<=c;i++){
        int nex=i;
        while(nex<c && lim[nex+1].first == lim[i].first)
            nex ++;
        bool ok = false;
        for(int j=i;j<=nex && !ok;j++)
            if(rid[id][j-1] == 0)
                ok = true;
        if(!ok)
            return false;
        i = nex;
    }
    return true;
}
int main(){
    long long n;
    cin>>n>>c;
    char str[10];
    d_mul = 1;
    for(int i=1;i<=c;i++){
        scanf("%s", str);
        lim[i].first = str[0];
        scanf("%d", &lim[i].second);
        d_mul *= lim[i].second;
    }
    sort(lim+1, lim+1+c);
    vector<int> tmp;
    dfs(1, tmp);
    Matrix mat;
    for(map<vector<int>, int>::iterator iter=id.begin();iter!=id.end();iter++){
        for(int i=0;i<26;i++){
            vector<int> nexid = iter->first;
            bool has_lim = false;
            for(int j=1;j<=c;j++){
                if(lim[j].first == i+'A'){
                    nexid[j-1] = (nexid[j-1]+1)%lim[j].second;
                    has_lim = true;
                }
            }
            if(has_lim) mat.a[iter->second][id[nexid]] = 1;
        }
    }
    mat = mpow(mat, n);
    int ans = 0;
    for(int i=1;i<=idcnt;i++){
        if(!mat.a[1][i])
            continue;
        if(check(i))
            ans = (ans+mat.a[1][i])%MOD;
    }
    printf("%d\n", ans);

    return 0;
}

#include <cstdio>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#include <set>
#include <map>
using namespace std;
const int MOD = 12345;
const int STD_SIZE = 130;
int msize;
struct Matrix {
    int mat[STD_SIZE][STD_SIZE];
    Matrix () {memset(mat, 0, sizeof mat);}
    inline Matrix operator * (const Matrix & b) {
        Matrix ret;
        for(int i = 0; i<msize; i++)
            for(int j = 0; j<msize; j++)
                for(int k = 0; k<msize; k++)
                    ret.mat[i][j] = (ret.mat[i][j]+mat[i][k]*b.mat[k][j])%MOD;
        return ret;
    }
};
typedef long long LL;
map<char, vector<int> > mp;
int lvl[30], prd[30];
bool vis[STD_SIZE], nvalid[STD_SIZE];
int main () {
    LL N; int C;
    cin >> N;
    scanf("%d", &C);
    for(int i = 1; i<=C; i++) {
        char buf[10]; int val;
        scanf("%s%d", buf, &val);
        mp[buf[0]].push_back(val);
    }
    for(char chr = 'A'; chr <= 'Z'; chr++) {
        vector<int>&tmp = mp[chr];
        sort(tmp.begin(), tmp.end());
        tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
        lvl[chr-'A'+1] = 1;
        for(int i = 0; i<(int)tmp.size(); i++)
            lvl[chr-'A'+1] = lvl[chr-'A'+1]*tmp[i];
    }
    prd[0] = lvl[0] = 1;
    for(int i = 1; i<=26; i++)
        prd[i] = prd[i-1]*lvl[i];
    msize = prd[26];
    Matrix unit, mfac;
    for(int i = 0; i<msize; i++) unit.mat[i][i] = 1;
    for(int cur = 0; cur<msize; cur++) {
        for(int nxt = 0; nxt<26; nxt++) {
            if(mp['A'+nxt].size() == 0) continue ;
            int cbit = cur/prd[nxt]%lvl[nxt+1];
            int nbit = (cbit+1)%lvl[nxt+1];
            int delta = (nbit-cbit)*prd[nxt];
            mfac.mat[cur][cur+delta] ++;
        }
    }
    while(N) {
        if(N&1) unit = unit*mfac;
        mfac = mfac*mfac;
        N >>= 1;
    }
    int ans = 0;
    for(int chr = 0; chr<26; chr++) {
        vector<int>&tmp = mp['A'+chr];
        if(tmp.size() == 0) continue ;
        memset(vis, 0, sizeof vis);
        for(int i = 0; i<(int)tmp.size(); i++)
            for(int j = 0; j<lvl[1+chr]; j+=tmp[i])
                vis[j] = true;
        for(int i = 0; i<msize; i++) {
            int cbit = i/prd[chr]%lvl[chr+1];
            if(!vis[cbit]) nvalid[i] = true;
        }
    }
    for(int i = 0; i<msize; i++) {
        if(nvalid[i]) continue ;
        ans = (ans+unit.mat[0][i]);
    }
    cout << ans << '\n';
}
/*
11 2
A 6
B 2
*/

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
const int P=12345;
const int maxn=130;
int n,N,A[maxn];
bool B[maxn][maxn];

struct Tmtx{
	int a[maxn][maxn];int n;
	Tmtx(){}
	Tmtx(int _n,bool x=0){
		int i;n=_n,memset(a,0,sizeof a);
		for(i=0;i<n;++i)a[i][i]=x;
	}
	Tmtx Tpose()const{
		Tmtx b;register int i,j;
		for(i=0;i<n;++i)
		for(j=0;j<n;++j)b.a[i][j]=a[j][i];
		return b;
	}
	Tmtx operator *(const Tmtx &b)const{
		Tmtx c(n,0);register int k,i,j;
		for(i=0;i<n;++i)
		for(j=0;j<n;++j)
		for(k=0;k<n;++k)
			c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%P;
		return c;
	}
	bool operator ==(const Tmtx &b)const{
		register int i,j;
		for(i=0;i<n;++i)
		for(j=0;j<n;++j)
			if(a[i][j]!=b.a[i][j])return false;
		return true;
	}
	void print(){
		int i,j;
		for(i=0;i<n;++i){
			for(j=0;j<n;++j)cerr<<a[i][j]<<' ';
			cerr<<endl;
		}
	}
};
Tmtx pow(Tmtx x,LL k){
	Tmtx Fc=Tmtx(x.n,1);
	for(;k;k>>=1)k&1?Fc=Fc*x:0,x=x*x;
	return Fc;
}

namespace Ninit{
	char s[10];
	void init(){
		int ni,ai,i,j;
		cin>>n>>ni;
		for(i=0;i<26;++i)A[i]=1;
		for(i=0;i<ni;++i){
			scanf("%s%d",s,&ai),A[s[0]-'A']*=ai;
			for(j=0;j<123;++j)B[s[0]-'A'][j]|=(j%ai==0);
		}
	}
}

namespace Nsolve{
	Tmtx An,A0;
	int pw[maxn],ans;
	void solve(){
		int i,j,k,xi,flag;
		for(pw[0]=1,i=1;i<=26;++i)pw[i]=pw[i-1]*A[i-1];
		An.n=A0.n=N=pw[26];
		for(i=0;i<N;++i){
			for(k=0;k<26;++k)if(B[k][0]){
				xi=i/pw[k]%A[k];
				++A0.a[i][i-xi*pw[k]+(xi+1)%A[k]*pw[k]];
			}
		}
		An=pow(A0,n);
		A0.print();An.print();
		for(i=0;i<N;++i){
			for(flag=0,k=0;k<26;++k){
				if(!B[k][0])continue;
				if(!B[k][i/pw[k]%A[k]])flag=1;
			}
			if(!flag)ans=(ans+An.a[0][i])%P;
		}
		cout<<ans<<endl;
	}
}

int main(){
	//freopen("A.in","r",stdin);
	Ninit::init();
	Nsolve::solve();
	return 0;
}

//107D Hewr
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
using namespace std;
#define fo(i,a,b) for (int i = a; i <= b; ++i)
#define fd(i,a,b) for (int i = a; i >= b; --i)
#define fe(i,x) for (int i = g[x], y = E[i].y; i; i = E[i].l, y = E[i].y)
#define forall(i, x) for (typeof((x).begin()) i = (x).begin(); i != (x).end(); ++i)
#define pb push_back
#define SIZE(x) ((int) (x).size())
#define MP make_pair
#define fi first
#define se second
#define UNIQUE(x) x.resize(unique(x.begin(), x.end()) - x.begin())
#define clr(a,x) memset(&a, x, sizeof(a))
#define move(a,b) memcpy(&b, &a, sizeof(a))
#define Plus(a,b) (((LL) (a) + (b)) % mo)
#define Minus(a,b) ((((LL) (a) - (b) ) % mo + mo) % mo)
#define Mul(a,b) ((LL) (a) * (b) % mo)
#define updmin(a,b) (a = min(a, b))
#define updmax(a,b) (a = max(a, b))
#define sqr(x) ((x) * (x))

typedef long long LL;
typedef long double LD;
typedef pair<int, int> PII;
typedef vector<int> VI;

const int oo = ~0u >> 2, mo = 12345;
const int mn = 26, mm = 20, ms = 200;

struct REC{
    int h, v;
    REC(){}
    REC(int _h, int _v){ h = _h, v = _v; }
};
vector<REC> rec;

struct MAT{ int a[ms]; } e, f;

int s[ms][ms], co[mm];
bool one[mn];
VI g[mn];
int m, l, num_one;
LL n;

MAT times(MAT a, MAT b){
    MAT ret; clr(ret, 0);
    fo (i, 0, l) fo (j, 0, l)
        ret.a[s[i][j]] = ((LL) a.a[i] * b.a[j] + ret.a[s[i][j]]) % mo;
    return ret;
}

MAT calc(LL n){
    if (n == 1) return e;
    MAT ret;
    if (n & 1){
        ret = calc(n - 1);
        ret = times(ret, e);
    } else {
        ret = calc(n / 2);
        ret = times(ret, ret);
    }
    return ret;
}

int main(){
    cin >> n >> m;
    if (!n){
        printf("1\n");
        return 0;
    }
    fo (i, 1, m){
        char ch; int t;
        do { cin >> ch; } while (ch < 'A' || ch > 'Z');
        cin >> t;
        int h = ch - 'A';
        if (t == 1) num_one += !one[h], one[h] = 1;
        else g[ch - 'A'].pb(t);
    }
    l = 1;
    fo (i, 0, mn - 1) if (!one[i]) fo (j, 0, SIZE(g[i]) - 1){
        rec.pb(*(new REC(i, g[i][j])));
        l *= g[i][j];
    }
    --l;
    fo (X, 0, l) fo (Y, 0, l){
        int sum[mm], x = X, y = Y;
        fo (i, 0, SIZE(rec) - 1)
            sum[i] = (x + y) % rec[i].v, x /= rec[i].v, y /= rec[i].v;
        s[X][Y] = 0;
        fd (i, SIZE(rec) - 1, 0) s[X][Y] = s[X][Y] * rec[i].v + sum[i];
    }
    co[0] = 1; fo (i, 1, SIZE(rec)) co[i] = co[i - 1] * rec[i - 1].v;
    clr(e, 0), e.a[0] = num_one;
    fo (i, 0, SIZE(rec) - 1){
        int t = 0;
        fo (j, 0, SIZE(rec) - 1) if (rec[i].h == rec[j].h) t += co[j];
        e.a[t] = 1;
    }
    f = calc(n);
    int Ans = 0;
    fo (i, 0, l) if (f.a[i]){
        bool v[mm];
        int t = i;
        clr(v, 0);
        fo (j, 0, SIZE(rec) - 1){
            if (!(t % rec[j].v)) v[rec[j].h] = 1;
            t /= rec[j].v;
        }
        bool flag = 1;
        fo (j, 0, SIZE(rec) - 1) if (!v[rec[j].h]){ flag = 0; break; }
        if (flag)
            Ans = (Ans + f.a[i]) % mo;
    }
    cout << Ans << endl;
}

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;

typedef long long LL;

const int MO = 12345;
const int MAXN = 210;
const int MAXA = 26;

char crime[MAXN];
int mult[MAXN];
int f[MAXN][MAXN], g[MAXN][MAXN];
int c;
int state_tot;
LL n;

int remain[MAXN];
int rel_mult[MAXN];
int used[MAXA];

void init()
{
#ifdef __linux__
  scanf("%lld%d", &n, &c);
#else
  scanf("%I64d%d", &n, &c);
#endif
  for (int i = 0; i < c; ++i) {
    scanf(" %c%d", crime + i, mult + i);
  }
}

void f_cal(int step)
{
  if (step == c) {
    int sta, nsta;

    sta = 0;

    for (int i = 0; i < c; ++i) {
      sta += rel_mult[i] * remain[i];
    }

    for (int idx = 0; idx < MAXA; ++idx) {
      if (!used[idx]) continue;
      nsta = sta;
      for (int j = 0; j < c; ++j) {
	if (crime[j] - 'A' == idx) {
	  nsta -=  remain[j] * rel_mult[j];
	  nsta += (remain[j]+1)%mult[j] * rel_mult[j];
	}
      }

      ++f[sta][nsta];
    }
  }

  for (int i = 0; i < mult[step]; ++i) {
    remain[step] = i;
    f_cal(step + 1);
  }
}

void mult_cal(int g[][MAXN], int f[][MAXN]) {

  static int c[MAXN][MAXN];

  for (int i = 0; i < state_tot; ++i)
    for (int j = 0; j < state_tot; ++j) {
      c[i][j] = 0;
      for (int l = 0; l < state_tot; ++l) {
	c[i][j] += ((LL)g[i][l] * f[l][j])%MO;
	c[i][j] %= MO;
      }
    }

  for (int i = 0; i < state_tot; ++i)
    for (int j = 0; j < state_tot; ++j) g[i][j] = c[i][j];
}

void g_cal(LL n)
{
  memset(g, 0, sizeof(g));
  for (int i = 0; i < state_tot; ++i) g[i][i] = 1;

  for (; n; n >>= 1) {
    if (n&1) {
      mult_cal(g, f);
    }
    mult_cal(f, f);
  }
}

void ans_cal()
{
  int cur[MAXN];
  int vis[MAXA];
  int ans = 0;

  for (int i = 0; i < state_tot; ++i) {

    memset(vis, 0, sizeof(vis));
    int num = i;
    for (int j = c-1; j >= 0; --j)  {
      if (num%mult[j] == 0) vis[crime[j] - 'A'] = 1;
      num /= mult[j];
    }

    bool fl = 1;
    for (int j = 0; j < c; ++j)
      if (used[j] && !vis[j]) { fl = 0; break; }

    if (fl) {
      ans += g[0][i];
      ans %= MO;
    }
  }

  printf("%d\n", ans);
}

void solve()
{

  state_tot = 1;
  rel_mult[c-1] = 1;
  for (int i = 0; i < c; ++i) {
    state_tot *= mult[i];
  }
  for (int i = c-1; i > 0; --i) {
    rel_mult[i-1] = rel_mult[i] * mult[i];
  }

  memset(used, 0, sizeof(used));
  for (int i = 0; i < c; ++i)
    used[crime[i] - 'A'] = 1;

  memset(f, 0, sizeof(f));
  f_cal(0);

  // for (int i = 0; i < state_tot; ++i) {
  //   for (int j = 0; j < state_tot; ++j) printf("%d ", f[i][j]);
  //   puts("");
  // }

  g_cal(n);

  ans_cal();
}

int main()
{
  init();
  solve();
  return 0;
}

#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
const int mod=12345;
typedef int matrix[130][130];
typedef vector<int> VI;
int c;
long long n;

void mul(matrix c,matrix a,matrix b,int n)
{
    for(int i=0;i<n;i++)
        for(int j=0;j<n;j++)
        {
            c[i][j]=0;
            for(int k=0;k<n;k++)
                c[i][j]=(c[i][j]+(long long)a[i][k]*(long long)b[k][j])%mod;
            c[i][j]%=mod;
        }
}
void pow(matrix c,matrix a,int n,long long p)
{
    matrix d;
    memset(c,0,sizeof(matrix));
    for(int i=0;i<n;i++) c[i][i]=1;
    memcpy(d,a,sizeof(matrix));
    for(long long i=1;i<=p;i<<=1)
    {
        matrix t;
        //printf("i=%I64d %d\n",i,d[0][0]);
        if(i&p)
        {
            mul(t,c,d,n);
            memcpy(c,t,sizeof(matrix));
        }
        mul(t,d,d,n);
        memcpy(d,t,sizeof(matrix));
    }
}
int prod[26],pros[27];
VI fact[26];
VI decode(int s)
{
    VI r(26);
    for(int i=0;i<26;i++)
    {
        r[i]=s%pros[i+1];
        s/=pros[i+1];
    }
    return r;
}
int encode(VI &v)
{
    int r=0;
    for(int i=0;i<26;i++) r+=v[i]*pros[i];
    return r;
}
int main()
{
    scanf("%I64d%d",&n,&c);
    fill(prod,prod+26,1);
    for(int i=0;i<c;i++)
    {
        char str[1024];
        scanf("%s",str);
        int x,y=str[0]-'A';
        scanf("%d",&x);
        prod[y]*=x;
        fact[y].push_back(x);
    }
    pros[0]=1;
    for(int i=1;i<=26;i++)
        pros[i]=pros[i-1]*prod[i-1];
    int m=pros[26];
    matrix a={},b;
    for(int i=0;i<m;i++)
    {
        VI u=decode(i);
        for(int j=0;j<26;j++)
        {
            if(fact[j].size()==0) continue;
            VI v=u;
            v[j]=(v[j]+1)%prod[j];
            a[i][encode(v)]++;
        }
    }
    /*printf("m=%d\n",m);
    for(int i=0;i<m;i++)
    {
        for(int j=0;j<m;j++) printf("%3d",a[i][j]);
        puts("");
    }*/
    pow(b,a,m,n);

    /*for(int i=0;i<m;i++)
    {
        for(int j=0;j<m;j++) printf("%3d",b[i][j]);
        puts("");
    }*/
    int ans=0;
    for(int i=0;i<m;i++)
    {
        VI u=decode(i);
        bool ok=true;
        for(int j=0;j<26;j++)
        {
            if(fact[j].size()==0) continue;
            VI &curr=fact[j];
            bool flag=true;
            for(int k=0;k<(int)curr.size();k++)
            {
                if(u[j]%curr[k]==0)
                {
                    flag=false;
                    break;
                }
            }
            if(flag)
            {
                ok=false;
                break;
            }
        }
        if(ok)
        {
            ans=(ans+b[0][i])%mod;
        }
    }
    printf("%d\n",ans);
    return 0;
}

#include <bits/stdc++.h>

using namespace std;

#define pb push_back

typedef long long ll;

const int maxn = 130, maxa = 30, mod = 12345;

template <typename T> void add(T &a, ll b) { a = (a + b) % mod; }

struct mat {
	int n, m, mtx[maxn][maxn];
	mat(int _n, int _m, int val = 0) {
		memset(mtx, 0, sizeof(mtx)); n = _n, m = _m;
		for (int i = 0; i < n; ++i)
			mtx[i][i] = val;
	}
	void rebuild(int _n, int _m, int val = 0) { *this = mat(_n, _m, val); }
	int *operator [](int x) { return mtx[x]; }
	mat operator *(mat &x) {
		mat ans(n, x.m);
		for (int i = 0; i < n; ++i)
			for (int j = 0; j < x.m; ++j)
				for (int k = 0; k < m; ++k)
					add(ans[i][j], 1ll * mtx[i][k] * x[k][j]);
		return ans;
	}
	void operator *=(mat &x) { *this = *this * x; }
	mat operator ^(ll power) {
		mat ans(n, n, 1), a = *this;
		for (; power; power >>= 1, a *= a)
			if (power & 1)
				ans *= a;
		return ans;
	}
	void operator ^=(ll power) { *this = *this ^ power; }
};

int c, m, sz, size[maxa], mul[maxa];
bitset <maxn> mark[maxa], ok;
vector <int> in, vec[maxa];
char f;
ll n;

int get(vector <int> v) {
	int javab = 0;
	for (int i = 0; i < sz; ++i)
		javab = javab * mul[in[i]] + v[i];
	return javab;
}

int main(){
	cin >> n >> c;
	if (!c)
		return cout << "0\n", 0;
	for (int i = 0, k; i < c; ++i) {
		cin >> f >> k;
		vec[f - 'A'].pb(k);
		in.pb(f - 'A');
	}
	sort(in.begin(), in.end());
	in.resize(unique(in.begin(), in.end()) - in.begin());
	sz = in.size(), m = 1;
	for (auto i: in) {
		sort(vec[i].begin(), vec[i].end());
		vec[i].resize(unique(vec[i].begin(), vec[i].end()) - vec[i].begin());
		size[i] = vec[i].size();
		mul[i] = 1;
		for (auto j: vec[i])
			mul[i] *= j;
		m *= mul[i];
		for (int j = 0; j < mul[i]; ++j) {
			bool flag = false;
			for (auto k: vec[i])
				if (!(j % k))
					flag = true;
			if (flag)
				mark[i][j] = true;
		}
	}
	mat base_m(1, m), main_m(m, m); base_m[0][0]++;
	vector <int> v(sz, 0); v[0] = -1;
	for (int i = 0; i < m; ++i) {
		int pos = 0;
		while (++v[pos] == mul[in[pos]])
			v[pos++] = 0;
		ok[i] = true;
		for (int j = 0; j < sz; ++j)
			ok[i] = ok[i] & mark[in[j]][v[j]];
		int st = get(v);
		for (int j = 0; j < sz; ++j) {
			v[j] = (v[j] + 1) % mul[in[j]];
			int end = get(v);
			v[j] = (v[j] + mul[in[j]] - 1) % mul[in[j]];
			main_m[st][end]++;
		}
	}
	main_m ^= n;
	base_m *= main_m;
	int ans = 0;
	v.resize(sz); v[0] = -1;
	for (int j = 1; j < sz; ++j)
		v[j] = 0;
	for (int i = 0; i < m; ++i) {
		int pos = 0;
		while (++v[pos] == mul[in[pos]])
			v[pos++] = 0;
		if (ok[i])
			add(ans, base_m[0][get(v)]);
	}
	cout << ans << '\n';
	return 0;
}

#include <cstdio>
#include <vector>
#include <iostream>
#define MOD 12345
using namespace std;
struct matrix
{
  int a[150][150];
}matmp,mat,matans,C;
struct box
{
  int rem[26];
}s[150];
int m,rem[26],ans,a[26]; long long int n;
vector<int> ok[26];
vector<int>::iterator it;
void add_state()
{
  m++;
  for(int i=0;i<26;i++) s[m].rem[i] = rem[i];
}
void dfs(int p)
{
  if(p == 26){
    add_state();
    return;
  }
  if(!ok[p].size()) {dfs(p+1);return;}
  for(int i=0;i<a[p];i++)
    rem[p]=i,dfs(p+1);
  return;
}
int trans(int s1,int s2)
{
  int cnt=0,i,cnt1=0;
  for(i=0;i<26 && cnt<=1;i++)
    if(ok[i].size())
      {
	if(a[i] == 1) {cnt1++;continue;}
	if(s[s2].rem[i] == (s[s1].rem[i]+1)%a[i]) cnt++;
	else if(s[s1].rem[i] == s[s2].rem[i]) continue;
	else return 0;
      }
  if(cnt == 1) return 1;
  if(cnt1 && cnt==0) return cnt1;
  return 0;
}
bool chk(int s1)
{
  for(int i=0;i<26;i++)
    if(ok[i].size())
      {
	for(it=ok[i].begin();it!=ok[i].end();it++)
	  if(s[s1].rem[i]%(*it) == 0)
	    break;
	if(it == ok[i].end()) return false;
      }
  return true;
}
void multi(matrix A,matrix B)
{
  int i,j,k;
  for(i=0;i<=m;i++)
    for(j=0;j<=m;j++)
      C.a[i][j] = 0;
  for(k=0;k<=m;k++)
    for(i=0;i<=m;i++)
      for(j=0;j<=m;j++)
	C.a[i][j] += A.a[i][k]*B.a[k][j];
}
void matpow(long long int x)
{
  long long int b; int i,j;
  for(i=0;i<=m;i++) for(j=0;j<=m;j++) matans.a[i][j]=0;
  for(i=0;i<=m;i++) matans.a[i][i] = 1;
  for(b=1;b<=x;b*=2)
    {
      if(b & x)
	{
	  multi(matans,mat);
	  matans = C;
	}
      multi(mat,mat);
      mat = C;
    }
}
int main()
{
  //freopen("input.txt","r",stdin);
  //freopen("output.txt","w",stdout);
  int i,j,c,x; char ch;
  cin>>n>>c;
  for(i=0;i<26;i++) a[i] = 1;
  for(i=1;i<=c;i++)
    {getchar();
      scanf("%c",&ch);
      scanf("%d",&x);
      ok[ch-'A'].push_back(x);
      a[ch-'A'] *= x;
    }
  dfs(0);
  for(i=1;i<=m;i++)
    for(j=1;j<=m;j++)
      mat.a[i][j] = trans(i,j);
  matpow(n);
  for(i=1;i<=m;i++)
    if(chk(i))
      ans = (ans+matans.a[1][i])%MOD;
  cout<<ans;
}

/*
ID: hamed_51
PROG: ?
LANG: C++
*/

#include <iostream>
#include <iomanip>
#include <fstream>
#include <sstream>
#include <cmath>
#include <cstdio>
#include <string>
#include <vector>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <map>
#include <queue>
#include <set>
#include <queue>
#include <stack>
#include <list>
#include <deque>
#include <assert.h>
#include <ctime>
#include <bitset>
#include <numeric>
#include <complex>
using namespace std;

#if (_win32 || __win32__)
#define lld "%i64d"
#else
#define lld "%lld"
#endif

#define FOREACH(i, c) for(__typeof((c).begin()) i = (c).begin(); i != (c).end(); ++i)
#define FOR(i, a, n) for (register int i = (a); i < (int)(n); ++i)
#define Size(n) ((int)(n).size())
#define all(n) (n).begin(), (n).end()
#define ll long long
#define pb push_back
#define error(x) cerr << #x << " = " << x << endl;
#define ull unsigned long long
#define pii pair<int, int>
#define pll pair<ll, ll>
#define point complex<double>
#define X real()
#define Y imag()
#define EPS 1e-8

struct mat {
	int w[123];
};

int bel[10], val[10], sz, lim;
int table[123][123];
const int MOD = 12345;
mat unit, c;

void mul(mat &a, mat b) {
	FOR(i, 0, lim) c.w[i] = 0;
	FOR(i, 0, lim) FOR(j, 0, lim) {
		c.w[table[i][j]] += a.w[i]*b.w[j];
		c.w[table[i][j]] %= MOD;
	}
	a = c;
}

mat power(ll y) {
	if (y == 1) return unit;
	if (y%2 == 1) {
		mat tmp = power(y-1);
		mul(tmp, unit);
		return tmp;
	}
	mat res = power(y/2);
	mul(res, res);
	return res;
}

int main() {
	ll n;
	int c;
	vector<int> V[26];
	bool one[26];
	memset(one, 0, sizeof one);
	cin >> n >> c;
	FOR(i, 0, c) {
		string s;
		int m;
		cin >> s >> m;
		if (m == 1)
			one[s[0]-'A'] = true;
		else
			V[s[0]-'A'].pb(m);
	}
	if (n == 0) {
		cout << 1 << endl;
		return 0;
	}
	int totone = 0;
	FOR(i, 0, 26) if (one[i]) totone++;
	sz = 0;
	lim = 1;
	FOR(i, 0, 26) FOR(j, 0, Size(V[i])) {
		bel[sz] = i;
		val[sz] = V[i][j];
		lim *= V[i][j];
		sz++;
	}
	FOR(i, 0, lim) FOR(j, 0, lim) {
		int A = i;
		int B = j;
		int sum[10];
		FOR(k, 0, sz) {
			sum[k] = (A%val[k] + B%val[k]) % val[k];
			A /= val[k];
			B /= val[k];
		}
		int C = 0;
		for (int k = sz-1; k >= 0; k--) {
			C *= val[k];
			C += sum[k];
		}
		table[i][j] = C;
	}

	FOR(i, 0, lim) unit.w[i] = 0;
	unit.w[0] = totone;

	int co[10];
	co[0] = 1;
	FOR(i, 0, sz) co[i+1] = co[i]*val[i];

	FOR(i, 0, sz) {
		int ind = 0;
		FOR(j, 0, sz) if (bel[i] == bel[j]) ind += co[j];
		unit.w[ind] = 1;
	}

	mat res = power(n);
	set<int> univ;
	FOR(i, 0, sz) univ.insert(bel[i]);
	int ans = 0;
	FOR(mask, 0, lim) {
		int dec[10];
		int tmp = mask;
		FOR(i, 0, sz) dec[i] = tmp%val[i], tmp /= val[i];
		set<int> sub;
		FOR(i, 0, sz) if (dec[i] == 0) sub.insert(bel[i]);
		if (sub == univ) ans = (ans+res.w[mask])%MOD;
	}
	cout << ans << endl;
	return 0;
}

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int op=12345;
LL n;
int C,m,a[1100],b[1100],Q=0,ans=0;
char s[10],c[1100];
pair<char,int>e[1100];
int f[150][150],g[150][150],h[150],u[150],q[50][150];
void _pow()
{
	for(int i=0;i<b[m];++i)
		for(int j=0;j<b[m];++j)
		{
			g[i][j]=0;
			for(int k=0;k<b[m];++k)
				g[i][j]=(g[i][j]+f[i][k]*f[k][j])%op;
		}
	for(int i=0;i<b[m];++i)
		for(int j=0;j<b[m];++j)
			f[i][j]=g[i][j];
}
void Gans()
{
	memset(h,0,sizeof(h));
	h[0]=1;
	for(;n>0;n>>=1)
	{
		if ( n&1 )
		{
			for(int i=0;i<b[m];++i)
			{
				u[i]=0;
				for(int j=0;j<b[m];++j)
					u[i]=(u[i]+h[j]*f[j][i])%op;
			}
			for(int i=0;i<b[m];++i) h[i]=u[i];
		}
		_pow();
	}
}
void dfs(const int x,const int y)
{
	if ( x>m ) { ans+=h[y];return;}
	for(int i=0;i<a[x];++i)
		if ( q[x][i] )
		dfs(x+1,y+b[x-1]*i);
}
int main()
{
	scanf("%I64d%d",&n,&C);
	for(int i=1,x;i<=C;++i)
	{
		scanf("%s%d",s+1,&x);
		e[i]=make_pair(s[1],x);
	}
	sort(e+1,e+1+C);
	m=1;
	a[1]=e[1].second,c[1]=e[1].first;b[0]=1;
	for(int i=2;i<=C;++i)
	{
		if ( e[i].first!=e[i-1].first )
		{
			if ( a[m]!=1 )
				b[m]=b[m-1]*a[m],a[++m]=1;
			else ++Q;
			c[m]=e[i].first;
		}
		a[m]*=e[i].second;
	}
	if ( a[m]>1 ) b[m]=b[m-1]*a[m];else --m;
	for(int i=0;i<b[m];++i)
		for(int j=1;j<=m;++j)
			if ( i%b[j]>=b[j-1] ) f[i-b[j-1]][i]=1;
				else f[i+b[j]-b[j-1]][i]=1;
	for(int i=0;i<b[m];++i)
		f[i][i]=Q;
	Gans();
	for(int i=1,j=1;i<=C;++i)
	{
		while(c[j]<e[i].first && j<=m ) ++j;
		if ( j>m ) break;
		if ( c[j]!=e[i].first ) continue;
		for(int k=0;k<a[j];k+=e[i].second )
			q[j][k]=1;
	}
	dfs(1,0);
	cout<<ans%op<<endl;
	return 0;
}

#pragma comment(linker, "/STACK:102400000,102400000")
#include <cstdlib>
#include <cctype>
#include <cstring>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <vector>
#include <string>
#include <iostream>
#include <sstream>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <fstream>
#include <numeric>
#include <iomanip>
#include <bitset>
#include <list>
#include <stdexcept>
#include <functional>
#include <utility>
#include <ctime>
using namespace std;
typedef long long LL;
typedef unsigned long long ULL;
#define MEM(a,b) memset((a),(b),sizeof(a))
const LL INF = 1e9 + 7;
const int N = 2e2 + 10;
class Matrix
{
	int a[N][N];
	int n;
public:
	Matrix ones(int n)
	{
		Matrix ret(n);
		for (int i = 0; i < n; i++) ret[i][i] = 1;
		return ret;
	}
	Matrix(int n = 0)
	{
		init(n);
	}
	void init(int n)
	{
		this->n = n;
		MEM(a, 0);
	}
	int* operator [] (int i)
	{
		return a[i];
	}
	Matrix operator + (Matrix &m)
	{
		Matrix ret(*this);
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				a[i][j] += m[i][j];
				if (a[i][j] >= INF) a[i][j] -= INF;
			}

		}
	}
	Matrix operator *(Matrix &m)
	{
		Matrix ret(n);
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
				{
					ret[i][j] = (ret[i][j] + 1LL * a[i][k] * m[k][j]) % INF;
				}
			}
		}
		return ret;
	}
	Matrix operator ^(LL b)
	{
		Matrix ret = ones(n);
		Matrix a = *this;
		while (b)
		{
			if (b & 1) ret = ret * a;
			a = a * a;
			b >>= 1;
		}
		return ret;
	}
};
int gcd(int n, int m)
{
	return m == 0 ? n : gcd(m, n%m);
}
int v[N];
int a[N];
int w[N];
int flag[N][N];
int key[N];
int main()
{
	//freopen("input.txt", "r", stdin);
	//freopen("output.txt", "w", stdout);
	map<char, int> mc;
	LL n;
	int m;
	cin >> n >> m;
	vector<pair<char, int>> vp;
	int tot = 1;
	for (int i = 0; i < m; i++)
	{
		char c;
		int x;
		cin >> c >> x;
		mc[c] = 1;
		flag[c][x] = 1;
	}
	for (int i = 'A'; i <= 'Z'; i++)
	{
		int cur = 1;
		for (int j = 1; j < N; j++)
		{
			if (flag[i][j] == 0) continue;
			for (int k = j + j; k < N; k += j) flag[i][k] = 0;
			cur *= j;
			if (vp.empty() || vp.back().first != i) vp.push_back({ i,cur });
			else vp.back().second = cur;
			tot *= j;
		}
		for (int j = 1; j < N; j++)
		{
			if (flag[i][j] == 0) continue;
			for (int k = j; k < N; k += j) flag[i][k] = 1;
			flag[i][0] = 1;
		}
	}
	int sz = 0;
	for (auto &p : vp) v[sz++] = p.second;
	v[sz] = 1;
	w[0] = 1;
	for (int i = 1; i < sz; i++) w[i] = v[i - 1] * w[i - 1];
	vector<int> ans;
	for (int i = 0; i < tot; i++)
	{
		MEM(key, 0);
		int cur = i;
		for (int j = 0; j < sz; j++)
		{
			int x = cur % v[j];
			cur /= v[j];
			if (flag[vp[j].first][x])
				key[vp[j].first] = 1;
		}
		if (count(key, key + N, 1) == mc.size()) ans.push_back(i);
	}
	Matrix b(tot);
	for (int i = 0; i < tot; i++)
	{
		int cur = i;
		for (int j = 0; j < sz; j++)
		{
			int x = cur % v[j];
			cur /= v[j];
			int y = (x + 1) % v[j];
			b[i][i - (x - y)*w[j]]++;
		}
	}
	b = b ^ n;
	int ret = 0;
	for (auto &x : ans)
	{
		ret += b[0][x];
		if (ret >= INF) ret -= INF;
	}
	printf("%d\n", ret);
	return 0;
}

#include <cstdio>
#include <numeric>
#include <iostream>
#include <vector>
#include <set>
#include <cstring>
#include <string>
#include <map>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <bitset>
#include <queue>
#include <sstream>
#include <deque>

using namespace std;

#define mp make_pair
#define pb push_back
#define rep(i,n) for(int i = 0; i < (n); i++)
#define re return
#define fi first
#define se second
#define sz(x) ((int) (x).size())
#define all(x) (x).begin(), (x).end()
#define sqr(x) ((x) * (x))
#define sqrt(x) sqrt(abs(x))
#define y0 y3487465
#define y1 y8687969
#define fill(x,y) memset(x,y,sizeof(x))

typedef vector<int> vi;
typedef long long ll;
typedef long double ld;
typedef double D;
typedef pair<int, int> ii;
typedef vector<ii> vii;
typedef vector<string> vs;
typedef vector<vi> vvi;

template<class T> T abs(T x) { re x > 0 ? x : -x; }

const int mod = 12345;

ll n;
int m;

vii v;

int g[123][123], u[123][123], z[123][123];
int was[26], use[26];

int main () {
    cin >> n >> m;
    int K = 1;
    for (int i = 0; i < m; i++) {
        char c;
        int x;
        cin >> c >> x;
        was[c - 'A'] = 1;
        if (x > 1) {
            was[c - 'A'] = 2;
            v.pb (mp (x, c - 'A'));
        }
        K *= x;
    }
    for (int i = 0; i < K; i++) {
        vi w;
        int k = i;
        for (int j = 0; j < sz (v); j++) {
            w.pb (k % v[j].fi);
            k /= v[j].fi;
        }
        for (int j = 0; j < 26; j++) {
            if (!was[j]) continue;
            int cur = 0;
            for (int k = sz (v) - 1; k >= 0; k--)
                if (v[k].se == j)
                    cur = (cur * v[k].fi + (w[k] + 1) % v[k].fi);
                else
                    cur = (cur * v[k].fi + w[k]);
            g[i][cur]++;
        }
    }
    for (int i = 0; i < K; i++)
        u[i][i] = 1;
    while (n) {
        if (n & 1) {
            for (int i = 0; i < K; i++)
                for (int j = 0; j < K; j++) {
                    ll tmp = 0;
                    for (int k = 0; k < K; k++)
                        tmp += u[i][k] * g[k][j];
                    z[i][j] = tmp % mod;
                }
            for (int i = 0; i < K; i++)
                for (int j = 0; j < K; j++)
                    u[i][j] = z[i][j];
        }
        n /= 2;
        for (int i = 0; i < K; i++)
            for (int j = 0; j < K; j++) {
                ll tmp = 0;
                for (int k = 0; k < K; k++)
                    tmp += g[i][k] * g[k][j];
                z[i][j] = tmp % mod;
            }
        for (int i = 0; i < K; i++)
            for (int j = 0; j < K; j++)
                g[i][j] = z[i][j];
    }
    int ans = 0;
    for (int i = 0; i < K; i++) {
        memset (use, 0, sizeof (use));
        int k = i;
        for (int j = 0; j < sz (v); j++) {
            int t = k % v[j].fi;
            k /= v[j].fi;
            if (t == 0) use[v[j].se] = 1;
        }
        int ok = 1;
        for (int j = 0; j < 26; j++)
            if (was[j] == 2 && use[j] == 0)
                ok = 0;
        ans = (ans + ok * u[0][i]) % mod;
    }
    printf ("%d\n", ans);
    return 0;
}

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<ctime>
#include<assert.h>

#include<cmath>
#include<iostream>
#include<fstream>

#include<string>
#include<vector>
#include<queue>
#include<map>
#include<algorithm>
#include<set>
#include<sstream>
#include<stack>
using namespace std;

#define asdf exit( 0);

#define MAX_N 150
#define MOD 12345

int ones;
long long n;
int mat_len;
set<int> s[30];
bool civ[30][200];

int simples[500],si;
vector< vector<int> > complx;

int lsg(int a,int b){ return (a*b)/(__gcd(a,b)); }

void ini()
{
    int i;
    for(i=0;i<28;i++) s[i].clear();
    memset(civ,0,sizeof(civ));
    si=0;
    complx.clear();
}

struct MAT
{
    int A[ MAX_N+7][ MAX_N+7];
} Ret,Base,Mult,Sol;

void View( MAT &m)
{
    int i,j;
    for( i=0;i<mat_len;i++){
        for( j=0;j<mat_len;j++){
            printf(" %d",m.A[i][j]);
        }
        printf("\n");
    }
    printf("\n");
}

MAT &operator*( MAT &m1,MAT &m2)
{
    int i,j,k;
    for( i=0;i<mat_len;i++){
        for( j=0;j<mat_len;j++){
            Sol.A[i][j] =0;
            for( k=0;k<mat_len;k++){
                Sol.A[i][j]+=(m1.A[i][k]*m2.A[k][j]);
                Sol.A[i][j] %=MOD;
            }
        }
    }
    return Sol;
}

void Pow( long long n)
{
    if( n==1){
        Ret =Base;
    }
    else if( n%2){
        Pow( n-1);
        Ret =Ret*Base;
    }
    else{
        Pow( n/2);
        Ret =Ret*Ret;
    }
}

int diff(vector<int> a,vector<int> b)
{
    int i,ok=0,eq=0;
    for(i=0;i<a.size();i++)
    {
        if(a[i]==b[i]) eq++;
        else if( (a[i]==((b[i]+1)%simples[i])) ) ok++;
    }
    if(  ((eq+1)==a.size()) && ok==1 ) return 1;
    return 0;
}

//some ones
int calc_simple()
{

    int i,j;

    memset(Base.A,0,sizeof(Base.A));

    mat_len=1;
    for(i=0;i<si;i++) mat_len*=simples[i];
    for(i=0;i<mat_len;i++)
        Base.A[i][i]+=ones;

    vector< vector<int> > states;
    vector<int> v;

    for(i=0;i<si;i++) v.push_back(0);

    states.push_back(v);

    //making al the states
    if(si)while(1)
    {
        for(i=si-1;i>=0;i--)
        {
            if( v[i]<(simples[i]-1))
                break;
        }
        if(i==-1) break;
        v[i]++;
        for(i=i+1;i<si;i++) v[i]=0;
        states.push_back(v);
    }
    /*for(i=0;i<states.size();i++)
    {
        for(j=0;j<states[i].size();j++)
        {
            cout<<states[i][j]<<" ";
        }
        cout<<endl;
    }
    asdf*/

    //cout<<simples[0]<<" "<<simples[1];
    //asdf
   // cout<<" "<<diff(states[0],states[2])<<endl;
   // cout<<" "<<diff(states[0],states[3])<<endl;
   // cout<<" "<<diff(states[0],states[4])<<endl;
   //  asdf

    //View(Base);

    for(i=0;i<mat_len;i++)
    {
        for(j=0;j<mat_len;j++)
        {
            if(i==j) continue;
            if(diff(states[i],states[j])==1)
            {
                Base.A[i][j]++;
            }
        }
    }
   // View(Base);
   // asdf

    Pow(n);
   // View(Ret);

   // asdf
    return Ret.A[0][0]%MOD;
}

int calc(int id)
{
    int ret=0;
    //cout<<"2s";
    if(id==complx.size())
    {
       // cout<<"4s";
       // asdf
        ret=calc_simple();
        return ret;
    }
    //cout<<"s1";

    int till=(1<<( complx[id].size() ))-1;
    int l=1,i,j;
    for(i=1;i<=till;i++)
    {
        for(j=0;j<complx[id].size();j++)
        {
            if( i&(1<<j) ) l=lsg(l,complx[id][j] );
        }
        simples[si-id-1]=l;
        if( (__builtin_popcount(i))%2 )
        {
             ret=(ret+calc(id+1) )%MOD;
        }
        else
        {
            ret-=calc(id+1);
            ret%=MOD;
            ret=(ret+MOD)%MOD;
        }
    }
    return ret;
}

int main()
{
    int T,i,u,v,j,k,num,c;

    //freopen("in.txt","r",stdin);

    scanf("%I64d %d",&n,&c);
    {
        ini();

        for(j=0;j<c;j++)
        {
            char in[12];
            int num,id,ok=1;
            scanf("%s %d",in,&num);

            id=in[0]-'A';

            if(!civ[id][num]) s[id].insert(num);

            for(i=num;i<150;i+=num)
            {
                if(civ[id][i]) s[id].erase(i);
                civ[id][i]=1;
            }

            //cout<<s[id].size()<<endl;
        }
        //asdf

        if(n==0)
        {
            printf("1\n");
            return 0;
        }

        ones=0;

        for(i=0;i<26;i++)
        {
            if(s[i].size())
            {
                //cout<<"s";
                if(*s[i].begin()==1){ ones++;continue;}
                if(s[i].size()==1){  simples[si++]=(*s[i].begin());continue;}

                vector<int> v;
                for(set<int>::iterator it=s[i].begin();it!=s[i].end();it++)
                {
                    v.push_back(*it);
                }
                complx.push_back(v);
            }
        }
        si+=complx.size();

        //cout<<si<<" "<<ones;

        //asdf

        int ans=calc(0)%MOD;
        ans=(ans+MOD)%MOD;

        printf("%d\n",ans);

    }
    return 0;
}

#include <cstdio>
#include <cstdlib>
#include <cassert>
#include <iostream>
#include <set>
#include <vector>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <map>
using namespace std;
typedef long long ll;
typedef vector<ll> vi;
typedef vector<vi> vvi;
typedef vector<double> vd;
typedef pair<int, int> pii;
typedef pair<double, double> pdd;
typedef vector<pii> vii;

const ll mod = 12345;
vi ind, modes;

vvi mul(const vvi & a, const vvi & b) {
    vvi res(a.size(), vi(a.size()));
    for (int i = 0; i < res.size(); ++i) for (int j = 0; j < res[i].size(); ++j) {
        res[i][j] = 0;
        for (int l = 0; l < res.size(); ++l)
            res[i][j] += a[i][l] * b[l][j];
        res[i][j] %= mod;
    }
    return res;
}

vvi id (int n) {
    vvi res(n, vi(n));
    for (int i = 0; i < n; ++i)
        res[i][i] = 1;
    return res;
}

vvi mpow (vvi x, ll n) {
    vvi res = id(x.size());
    while (n) {
        if (n % 2)
            res = mul(res, x);
        n /= 2;
        x = mul(x, x);
    }
    return res;
}

vi get_rem (int tot) {
    vi res;
    for (int i = 0; i < modes.size(); ++i) {
        res.push_back(tot % modes[i]);
        tot /= modes[i];
    }
    return res;
}

int get_num (const vi & rems) {
    int res = 0;
    for (int i = modes.size() - 1; i >= 0; --i)
        res = res * modes[i] + rems[i];
    return res;
}

int main() {
    ll n, c;
    cin >> n >> c;
    vector<vi> kr(26);
    if (c == 0) {
        cout << 0 << endl;
        return 0;
    }
    for (int i = 0; i < c; ++i) {
        string s;
        int t;
        cin >> s >> t;
        kr[s[0] - 'A'].push_back(t);
    }
    int tot = 1;
    for (int i = 0; i < 26; ++i) {
        if (!kr[i].empty()) {
            ind.push_back(i);
            modes.push_back(1);
            for (int l = 0; l < kr[i].size(); ++l) {
                modes.back() *= kr[i][l];
                tot *= kr[i][l];
            }
        }
    }
    vector<vi> base(tot, vi(tot, 0));
    for (int num = 0; num < tot; ++num) {
        vi rems = get_rem(num);
        for (int i = 0; i < modes.size(); ++i) {
            rems[i] = (rems[i] + 1) % modes[i];
            ++base[get_num(rems)][num];
            rems[i] = (rems[i] + modes[i] - 1) % modes[i];
        }
    }
    vvi res = mpow(base, n);
    ll ans = 0;
    for (int i = 0; i < tot; ++i) {
        vi cur = get_rem(i);
        for (int l = 0; l < modes.size(); ++l) {
            bool ok = 0;
            for (int j = 0; j < kr[ind[l]].size(); ++j)
                if (cur[l] % kr[ind[l]][j] == 0)
                    ok = 1;
            if (!ok)
                res[i][0] = 0;
        }
        ans += res[i][0];
    }
    cout << ans % mod << endl;
    return 0;
}

#include <cstdio>
#include <cstring>

#include <vector>
#include <algorithm>

using namespace std;
typedef long long llint;

const llint mod = 12345;

llint N; int C;
char c; int mu;
int tot;

int p[ 26 ];
int lcm[ 26 ];
vector< int > d[ 26 ];

inline void unpack( int rank ) {
  for( int i = 0; i < 26; ++i ) {
    p[i] = rank % lcm[i];
    rank /= lcm[i];
  }
}

inline int repack() {
  int ret = p[25];

  for( int i = 24; i >= 0; --i )
    ret = ret * lcm[i] + ( p[i] % lcm[i] );

  return ret;
}

int m[ 124 ][ 124 ];
int r[ 124 ][ 124 ];
int t[ 124 ][ 124 ];

inline void mult( int a[124][124], int b[124][124] ) {
  memset( t, 0, sizeof t );

  for( int i = 0; i < tot; ++i )
    for( int j = 0; j < tot; ++j )
      for( int k = 0; k < tot; ++k )
	t[i][j] = (int)( ( (llint)t[i][j] + (llint)a[i][k] * (llint)b[k][j] ) % mod );

  memcpy( a, t, sizeof t );
}

int main( void )
{
  scanf( "%I64%d", &N, &C );

  if( N == 0 ) {
    puts( "1" );
    return 0;
  }

  for( int i = 0; i < C; ++i ) {
    scanf( " %c%d", &c, &mu );
    d[c-'A'].push_back( mu );
  }

  tot = 1;

  for( int i = 0; i < 26; ++i ) {
    lcm[i] = 1;

    for( int j = 0; j < d[i].size(); ++j )
      lcm[i] = ( lcm[i] / __gcd( lcm[i], d[i][j] ) ) * d[i][j];

    tot *= lcm[i];
  }

  for( int i = 0; i < tot; ++i ) {
    unpack( i );

    for( int j = 0; j < 26; ++j ) {
      if( d[j].empty() ) continue;
      ++p[j];
      ++m[repack()][i];
      --p[j];
    }

    r[i][i] = 1;
  }

  for( int i = 0; ( 1LL << i ) <= N; ++i ) {
    if( ( ( N >> i )&1 ) == 1 ) mult( r, m );
    mult( m, m );
  }

  llint Sol = 0;

  for( int i = 0; i < tot; ++i ) {
    unpack( i );

    bool good = 1;
    for( int j = 0; j < 26; ++j ) {
      if( d[j].empty() ) continue;
      bool ok = 0;

      for( int k = 0; k < d[j].size(); ++k )
	if( p[j] % d[j][k] == 0 ) ok = 1;

      good = good && ok;
    }

    if( good ) Sol = ( Sol + r[i][0] ) % mod;
  }

  printf( "%d\n", (int)Sol );

  return 0;
}

#include <iostream>
#include <fstream>
#include <vector>
#include <set>
#include <map>
#include <string>
#include <cmath>
#include <cassert>
#include <ctime>
#include <algorithm>
#include <queue>
#include <memory.h>
#include <stack>
#define mp make_pair
#define pb push_back
#define setval(a,v) memset(a,v,sizeof(a))

#if ( _WIN32 || __WIN32__ )
    #define LLD "%I64d"
#else
    #define LLD "%lld"
#endif

using namespace std;

typedef long long int64;
typedef long double ld;

const int MOD = 12345;

int a[123][123];
int temp[123][123];
int res[123][123];
int mod[26];
bool good[26][123];
bool can[26];
int modmult;
int n;
int64 st;

void mult(int a[][123],int b[][123]){

//    cerr <<"!!!!!!!!!!!!"<<endl;
//    cerr << a[0][0] <<" "<<a[0][1] <<" "<<a[1][0] <<" "<<a[1][1] << endl;
  //  cerr << b[0][0] <<" "<<b[0][1] <<" "<<b[1][0] <<" "<<b[1][1] << endl;

    for (int i = 0; i < modmult; i++)
        for (int  j = 0; j < modmult; j++)
                 temp[i][j] = 0;
    for (int i = 0; i < modmult; i++)
        for (int  j = 0; j < modmult; j++)
            for (int  k = 0; k < modmult; k++) {
                 temp[i][j] += (a[i][k] * b[k][j]) % MOD;
                 if (temp[i][j] >= MOD)
                    temp[i][j] -= MOD;
            }

    for (int i = 0; i < modmult; i++)
        for (int  j = 0; j < modmult; j++)
                a[i][j] = temp[i][j];

//   cerr << a[0][0] <<" "<<a[0][1] <<" "<<a[1][0] <<" "<<a[1][1] << endl;
  // cerr <<"!!!!!!!!!!!!"<<endl;

}

int gennum(int *a){
    int num = 0;
    for (int i = 0; i < 26; i++){
  //      cerr << "!!!"<<mod[i] << endl;
        num = num * mod[i] + (a[i]+mod[i])%mod[i];
    }
    return num;
}

void genval(int mask,int* a){
    for (int i = 25; i >= 0; i--){
//        cerr << "???" << mod[i] << endl;
        a[i] = mask % mod[i];
        mask /= mod[i];
    }
}

vector<int> goodmask;

int b[26];

void per(int pos){
    if (pos == 26){
        goodmask.pb(gennum(b));
        return;
    }

    for (int i = 0; i < mod[pos]; i++)
        if (good[pos][i]){
            b[pos] = i;
            per(pos+1);
        }
}

void gen_next(int mask){
    int temp[26];
    genval(mask,temp);
    for (int i = 0; i < 26; i++)
        if (can[i]) {
            temp[i]++;
            a[mask][gennum(temp)] = 1;
            temp[i]--;
        }
}

int main()
{
  #ifndef ONLINE_JUDGE
    freopen("input.txt","r",stdin);
    freopen("output.txt","w",stdout);
  #endif
    cin >> st;
    cin >> n;
    for (int i = 0; i < 26; i++)
        mod[i] = good[i][0] = 1;
    modmult = 1;
    for (int i = 0; i < n; i++){
        char c;
        cin >> c;
        int tmp;
        cin >> tmp;
        mod[c - 'A'] *= tmp;
        can[c - 'A'] = true;
        modmult *= tmp;
        for (int j=0; j < 123;j++)
            good[c - 'A'][j] |= (j%tmp) == 0;
    }

//    for (int i = 0; i < 26; i++)
//        cerr << mod[i] << endl;

    for (int i = 0; i < modmult; i++){
    //   cerr << i << endl;
       gen_next(i);
    }

    //return 0;
    per(0);

    //return 0;

    memset(res,0,sizeof(res));

    /*for (int i = 0; i < modmult; i++)
        for (int j = 0; j < modmult; j++)
            cerr << a[i][j] <<" \n"[j==modmult-1];
    cerr << endl;*/

    res[0][0] = 1;
    for (; st; st/=2){
        if (st % 2)
            mult(res,a);
        mult(a,a);

       /* for (int i = 0; i < modmult; i++)
            for (int j = 0; j < modmult; j++)
                cerr << a[i][j] <<" \n"[j==modmult-1];
        cerr << endl;*/

    }

/*    for (int i = 0; i < modmult; i++)
        for (int j = 0; j < modmult; j++)
        cerr << res[i][j] <<" \n"[j==modmult-1];
    cerr << endl;*/

    int ans = 0;
    for (int i = 0; i < goodmask.size();i++){
         ans += res[0][goodmask[i]];
         ans %= MOD;
    }

    cout << ans << endl;

    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <queue>

#define LL long long
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define size(S) S.size()
#define PII pair<int, int>
#define PID pair<int, double>

using namespace std;

const int mo = 12345;
LL n;
int c, b, d[26][1010], p[26], cnt[26], all, gen[130], ova, tmp[26];
char a;
bool app[26];
struct matrix{
	int n, m, data[130][130];
} res, shift, ret, T;

matrix operator*(matrix a, matrix b){
	memset(T.data, 0, sizeof(T.data));
	T.n = a.n; T.m = b.m;
	for (int i = 0; i < a.n; i++)
		for (int j = 0; j < a.m; j++)
			for (int k = 0; k < b.m; k++)
				T.data[i][k] = (T.data[i][k] + a.data[i][j] * b.data[j][k]) % mo;
	return T;
}

void generate(int x, int v){
	if (x == 26) gen[ova++] = v;
	else for (int i = 0; i < p[x]; i++) generate(x + 1, v * p[x] + i);
}

void decode(int x){
	for (int i = 25; i >= 0; i--)
		tmp[i] = x % p[i], x /= p[i];
}

int code(){
	int ret = 0;
	for (int i = 0; i < 26; i++) ret = ret * p[i] + tmp[i];
	for (int i = 0; i < ova; i++) if (gen[i] == ret) return i;
	return -1;
}

void pow(LL x, matrix &s, matrix &ret){
	matrix tmp;
	for (ret = res, tmp = s; x; x >>= 1){
		if (x & 1) ret = ret * tmp;
		tmp = tmp * tmp;
	}
}

bool valid(){
	for (int i = 0; i < 26; i++){
		if (!app[i]) continue;
		bool find = false;
		for (int j = 0; j < cnt[i]; j++){
			if (tmp[i] % d[i][j] == 0){
				find = true;
				break;
			}
		}
		if (!find) return false;
	}
	return true;
}

int main(){
	freopen("d.in", "r", stdin);
	for (int i = 0; i < 26; i++) p[i] = 1;
	for (cin >> n >> c; c; c--){
		cin >> a >> b;
		int t = a - 'A';
		d[t][cnt[t]++] = b; p[t] *= b; app[t] = true;
	}
	all = 1;
	for (int i = 0; i < 26; i++) all *= p[i];

	generate(0, 0);
	res.n = 1; res.m = all; shift.n = shift.m = all;
	for (int i = 0; i < all; i++){
		for (int j = 0; j < 26; j++){
			if (!app[j]) continue;
			decode(gen[i]);
			tmp[j] = (tmp[j] + 1) % p[j];
			int p = code();
			shift.data[i][p] = 1;
		}
	}
	res.data[0][0] = 1;

	int ans = 0;
	pow(n, shift, ret);
	for (int i = 0; i < ova; i++){
		decode(gen[i]);
		if (valid()) ans = (ans + ret.data[0][i]) % mo;
	}
	cout << ans << endl;
	return 0;
}

#include<cstdio>
#include<cstring>
#include<iostream>

#define nn 210
#define mm 1010
#define Mod 12345
using namespace std;

char c[mm];
int h[nn],ck[nn],d[mm];long long l;
int st[nn],p[mm],tr[nn][nn],rs[nn][nn],n,m,N,ans;

inline void Get_arr(int a){
	for (int i=m;i>=1;i--) st[i]=a/p[i],a%=p[i];
}
inline int Get_id(int *a){
	int rs=0;
	for (int i=1;i<=m;i++) rs+=a[i]*p[i];
	return(rs);
}
inline void Get_tran(){
	p[1]=1;
	for (int i=2;i<=m;i++) p[i]=p[i-1]*d[i-1];
	N=p[m]*d[m];

	for (int i=0;i<N;i++){
		for (int j=0;j<26;j++) if(h[j]){
			Get_arr(i);
			for (int k=1;k<=m;k++) if(c[k]-'A'==j) st[k]=(st[k]+1)%d[k];
			tr[i][Get_id(st)]++;
		}
	}
}

int a[nn],b[nn][nn];
inline void Pow(){
	for (int i=0;i<N;i++) rs[i][i]=1;
	while (l){
		if (l&1){
			for (int i=0;i<N;i++)
			for (int j=0;j<N;j++) b[i][j]=rs[i][j],rs[i][j]=0;
			for (int k=0;k<N;k++)
			for (int i=0;i<N;i++)
			for (int j=0;j<N;j++) rs[i][j]=(rs[i][j]+b[i][k]*tr[k][j]%Mod)%Mod;
		}
		for (int i=0;i<N;i++)
		for (int j=0;j<N;j++) b[i][j]=tr[i][j],tr[i][j]=0;
		for (int k=0;k<N;k++)
		for (int i=0;i<N;i++)
		for (int j=0;j<N;j++) tr[i][j]=(tr[i][j]+b[i][k]*b[k][j]%Mod)%Mod;
		l/=2ll;
	}
}

int main()
{
	scanf("%I64d%d",&l,&m);
	if (!l) {puts("0");return(0);}
	for (int i=1;i<=m;i++){
		c[i]=getchar();
		while ('A'>c[i]||c[i]>'Z') c[i]=getchar();
		scanf("%d",&d[i]);h[c[i]-'A']=1;
	}

	Get_tran();
	Pow();

	for (int i=0;i<N;i++){
		Get_arr(i);
		bool jd=1;
		memset(ck,0,sizeof(ck));
		for (int j=1;j<=m;j++) if(!st[j]) ck[c[j]-'A']=1;
		for (int j=0;j<26;j++) if(h[j]&&!ck[j]) jd=0;
		if (jd) ans=(ans+rs[0][i])%Mod;
	}
	printf("%d\n",ans);
}

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<vector>
#include<algorithm>

using namespace std;

const int mo=12345;

int s,cnt,num,multi[30],c,pos[30];

long long n;

char st[3];

vector<int> status[125],nowway,v[30];

map< vector <int> , int > id;

struct matrix
{
	int z[125][125];
	matrix()
	{
		memset(z,0,sizeof(z));
	}
	matrix operator*(const matrix &a)const
	{
		matrix ans;
		for (int b=1;b<=s;b++)
			for (int c=1;c<=s;c++)
				for (int d=1;d<=s;d++)
					ans.z[b][c]=(ans.z[b][c]+z[b][d]*a.z[d][c]%mo)%mo;
		return ans;
	}
}m1,m2;

matrix mul(matrix a,long long b)
{
	matrix ans;
	for (int c=1;c<=s;c++)
		ans.z[c][c]=1;
	while (b)
	{
		if (b&1) ans=ans*a;
		a=a*a;
		b>>=1;
	}
	return ans;
}

void dfs(int now)
{
	if (now==cnt)
	{
		num++;
		status[num]=nowway;
		id[nowway]=num;
	}
	else
	{
		for (int a=0;a<multi[now];a++)
		{
			nowway.push_back(a);
			dfs(now+1);
			nowway.pop_back();
		}
	}
}

int gcd(int a,int b)
{
	if (a % b==0) return b;
	else return a;
}

int main()
{
	scanf("%I64d%d",&n,&c);
	for (int a=1;a<=c;a++)
	{
		scanf("%s",st);
		int nowv;
		scanf("%d",&nowv);
		v[st[0]-'A'+1].push_back(nowv);
	}
	s=1;
	for (int a=1;a<=26;a++)
		if (v[a].size())
		{
			sort(v[a].begin(),v[a].end());
			v[a].resize(unique(v[a].begin(),v[a].end())-v[a].begin());
			int size=0;
			for (int b=0;b<(int)v[a].size();b++)
			{
				bool able=true;
				for (int c=0;c<b;c++)
					if (v[a][b]%v[a][c]==0) able=false;
				if (able)
				{
					v[a][size]=v[a][b];
					size++;
				}
			}
			v[a].resize(size);
			if (v[a].back()==1) continue;
			int lcm=1;
			for (int b=0;b<(int)v[a].size();b++)
				lcm=lcm*v[a][b]/gcd(v[a][b],lcm);
			s*=lcm;
			multi[cnt]=lcm;
			pos[a]=cnt;
			cnt++;
		}
	dfs(0);
	for (int a=1;a<=num;a++)
	{
		nowway=status[a];
		for (int b=1;b<=26;b++)
			if (v[b].size())
			{
				if (v[b].back()==1) m1.z[a][a]++;
				else
				{
					nowway[pos[b]]++;
					nowway[pos[b]]%=multi[pos[b]];
					int idx=id[nowway];
					m1.z[a][idx]++;
					nowway[pos[b]]+=multi[pos[b]]-1;
					nowway[pos[b]]%=multi[pos[b]];
				}
			}
	}
	m2.z[1][1]=1;
	m2=m2*mul(m1,n);
	int ans=0;
	for (int a=1;a<=num;a++)
	{
		nowway=status[a];
		bool able=true;
		for (int b=1;b<=26;b++)
			if (v[b].size())
			{
				if (v[b].back()==1) continue;
				bool fail=true;
				for (int c=0;c<(int)v[b].size();c++)
					if (nowway[pos[b]]%v[b][c]==0)
					{
						fail=false;
						break;
					}
				if (fail)
				{
					able=false;
					break;
				}
			}
		if (able) ans=(ans+m2.z[1][a])%mo;
	}
	printf("%d\n",ans);

	return 0;
}

#include <iostream>
#include <iomanip>
#include <fstream>
#include <vector>
#include <array>
#include <algorithm>
#include <utility>
#include <map>
#include <queue>
#include <set>
#include <cmath>
#include <cstdio>
#include <cstring>

#define ll long long
#define ld long double
#define eps 1e-8
#define MOD 12345

#define INF 0x3f3f3f3f
#define INFLL 0x3f3f3f3f3f3f3f3f

// change if necessary
#define MAXN 1000000

using namespace std;

struct M {
    const static int n = 123;
    ll m[n][n];
    M() { memset(m, 0, sizeof m); }
    M operator*(const M& m2) {
        M res;
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < n; j++) {
                for (int a = 0; a < n; a++) {
                    res.m[i][j] += m[i][a] * m2.m[a][j];
                    if (res.m[i][j] >= MOD) res.m[i][j] %= MOD;
                }
            }
        }
        return res;
    }
    ll* operator[](const int &x) { return m[x]; }
    static M pow(M &m, ll e) {
        M res = I();
        while (e) {
            if (e & 1) res = res * m;
            m = m * m;
            e >>= 1;
        }
        return res;
    }
    static M I() {
        M m;
        for (int i = 0; i < n; i++) m.m[i][i] = 1;
        return m;
    }
};

int n, c;
vector<int> cond[30];
int prod[30];
int prod2[30];
int tot = 1;

int main() {
    cin.tie(0)->sync_with_stdio(0);

    cin >> n >> c;
    for (int i = 0; i < c; i++) {
        char t; int m; cin >> t >> m;
        cond[t - 'A'].push_back(m);
    }

    for (int i = 0; i < 26; i++) {
        if (!cond[i].empty()) {
            prod[i] = tot;
            for (int j : cond[i]) tot *= j;
            prod2[i] = tot;
        }
    }
    M m;
    for (int i = 0; i < tot; i++) {
        for (int j = 0; j < 26; j++) {
            if (prod[j]) {
                int nxt = (i + prod[j]) % prod2[j] + i / prod2[j] * prod2[j];
                m[i][nxt]++;
            }
        }
    }

    m = M::pow(m, n);
    ll ans = 0;
    for (int i = 0; i < tot; i++) {
        bool works = true;
        for (int j = 0; j < 26; j++) {
            if (prod[j]) {
                int val = (i % prod2[j]) / prod[j];
                bool any = false;
                for (int k : cond[j]) {
                    if (val % k == 0) {
                        any = true;
                        break;
                    }
                }
                if (!any) {
                    works = false;
                    break;
                }
            }
        }
        if (works) {
            ans += m[0][i];
            if (ans >= MOD) ans -= MOD;
        }
    }
    cout << ans << '\n';

    return 0;
}

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

const int mod = 12345;

struct node
{
    char str[5];
    int x;
    bool operator <(const node &b)const
    {
        return x>b.x;
    }
}a[1010];

int num[30];

bool vis[1010][125];

int g[130][130],tmp[130][130],ans[130][130];

int now[1010];

int tot,m;

void power(int y)
{
    int i,j,k;
    memset(ans,0,sizeof(ans));
    for(i=0;i<tot;i++)
        ans[i][i]=1;
    while(y)
    {
        if(y&1)
        {
            memset(tmp,0,sizeof(tmp));
            for(i=0;i<tot;i++)
                for(j=0;j<tot;j++)
                    for(k=0;k<tot;k++)
                        tmp[i][j]=(tmp[i][j]+ans[i][k]*g[k][j])%mod;
            for(i=0;i<tot;i++)
                for(j=0;j<tot;j++)
                    ans[i][j]=tmp[i][j];
        }
        memset(tmp,0,sizeof(tmp));
        for(i=0;i<tot;i++)
            for(j=0;j<tot;j++)
                for(k=0;k<tot;k++)
                    tmp[i][j]=(tmp[i][j]+g[i][k]*g[k][j])%mod;
        for(i=0;i<tot;i++)
            for(j=0;j<tot;j++)
                g[i][j]=tmp[i][j];
        y/=2;
    }
    return;
}

bool check(int y)
{
    int temp=y,i,j,flag;
    for(i=0;i<m;i++)
    {
        now[i]=temp%a[i].x;
        temp/=a[i].x;
    }
    for(i=0;i<26;i++)
    {
        flag=0;
        if(num[i]==0)
            continue;
        for(j=0;j<m;j++)
        {
            if((a[j].str[0]-'A'==i)&&(now[j]==0))
            {
                flag=1;
                break;
            }
        }
        if(flag==0)
            return false;
    }
    return true;
}

int main()
{
    int n,i,j,temp,k;
    tot=1;
    scanf("%d%d",&n,&m);
    memset(num,0,sizeof(num));
    memset(vis,0,sizeof(vis));
    for(i=0,j=0;i<m;i++,j++)
    {
        scanf("%s%d",a[j].str,&a[j].x);
        if(vis[a[j].str[0]-'A'][a[j].x]==1)
        {
            j--;
            continue;
        }
        vis[a[j].str[0]-'A'][a[j].x]=1;
        num[a[j].str[0]-'A']++;
        tot=tot*a[i].x;
    }
    m=j;
    //printf("%d\n",j);
    sort(a,a+m);
    int fuck=0;
    for(i=m-1;i>=0;i--)
    {
        if(a[i].x==1)
        {
            if(num[a[i].str[0]-'A']==1)
                fuck++;
        }
    }
    memset(g,0,sizeof(g));
    for(i=0;i<tot;i++)
    {
      //  printf("%d %d\n",i,tot);
        temp=i;
        for(j=0;j<m;j++)
        {
            now[j]=temp%a[j].x;
            temp/=a[j].x;
       //     printf("fuck %d %d %d\n",i,j,now[j]);
        }
        for(j=0;j<26;j++)
        {
            if(num[j]==0)
                continue;
            for(k=0;k<m;k++)
            {
                if(a[k].str[0]-'A'==j)
                    now[k]=(now[k]+1)%a[k].x;
            }
            temp=0;
            for(k=m-1;k>=0;k--)
            {
                temp=temp*a[k].x;
                temp=temp+now[k];
            }
            g[temp][i]=1;
            for(k=0;k<m;k++)
            {
                if(a[k].str[0]-'A'==j)
                    now[k]=(now[k]-1+a[k].x)%a[k].x;
            }
        }
        g[i][i]=fuck;
    }
/*
    for(i=0;i<tot;i++)
    {
        for(j=0;j<tot;j++)
            printf("%d ",g[i][j]);
        printf("\n");
    }
*/
    power(n);
/*
    for(i=0;i<tot;i++)
    {
        for(j=0;j<tot;j++)
            printf("%d ",ans[i][j]);
        printf("\n");
    }
*/
    int final=0;
    for(i=0;i<tot;i++)
    {
        if(check(i))
            final=(final+ans[0][i])%mod;
    }
    printf("%d\n",final);
    return 0;
}

#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define mod 12345

int total, cnt, f[66][205][205], answer[205], news[205], sum[1050], mul[1050];
char dif[205], ch[1050];
bool great[1050], can[1050][205];
vector <int> doing;
map <vector <int>, int> number;

int  Rand()
{
     return (rand() << 15) | rand();
}

void DFS(int current)
{
int  i, size;
bool solved;

     if  (current > total)
     {
         number[doing] = ++cnt;
         size = doing.size();
         solved = true;
         for (i = 0; i < size; i++)
         if  (!can[dif[i + 1]][doing[i]])
         {
             solved = false;
             break;
         }
         if  (solved)
         {
             great[cnt] = true;
         }

         return;
     }
     for (i = 0; i < sum[dif[current]]; i++)
     {
         doing.push_back(i);
         DFS(current + 1);
         doing.pop_back();
     }

     return;
}

int  main()
{
int  all, i, j, k, times, Log, result, current, next, size, temp;
long long n;
vector <int> vec;
map  <vector <int>, int> :: iterator it, it2;

//     freopen("d.in", "r", stdin);
//     freopen("d.out", "w", stdout);

     srand((unsigned) time (0));

     for (i = 'A'; i <= 'Z'; i++)
     {
         sum[i] = 1;
     }

     scanf("%I64d%d\n", &n, &all);
     total = 0;
     for (i = 1; i <= all; i++)
     {
         scanf("%c%d\n", &ch[i], &mul[i]);
         sum[ch[i]] *= mul[i];
         dif[++total] = ch[i];
     }

     sort(dif + 1, dif + total + 1);
     for (i = j = 1; i < total; i++)
     if  (dif[i + 1] != dif[j])
     {
         dif[++j] = dif[i + 1];
     }
     total = j;

     for (i = 1; i <= all; i++)
     {
         for (j = 0; j < sum[ch[i]]; j += mul[i])
         {
             can[ch[i]][j] = true;
         }
     }

     doing.clear();
     cnt = 0;
     DFS(1);

     for (it = number.begin(); it != number.end(); it++)
     {
         current = it -> second;
         vec = it -> first;
         size = vec.size();
         for (i = 0; i < size; i++)
         {
             temp = vec[i];
             vec[i] = (vec[i] + 1) % sum[dif[i + 1]];
             it2 = number.find(vec);
             next = it2 -> second;
             f[0][current][next]++;
             vec[i] = temp;
         }
     }

     Log = (int) (log2(n));
     for (times = 1; times <= Log; times++)
     {
         for (i = 1; i <= cnt; i++)
         {
             for (j = 1; j <= cnt; j++)
             {
                 for (k = 1; k <= cnt; k++)
                 {
                     f[times][i][j] += f[times - 1][i][k] * f[times - 1][k][j];
                     f[times][i][j] %= mod;
                 }
             }
         }
     }

     answer[1] = 1;
     for (times = Log; times >= 0; times--)
     if  ((1ll << times) <= n)
     {
         n -= 1ll << times;
         memset(news, 0, sizeof(news));
         for (i = 1; i <= cnt; i++)
         {
             for (j = 1; j <= cnt; j++)
             {
                 news[i] += f[times][i][j] * answer[j];
                 news[i] %= mod;
             }
         }
         memcpy(answer, news, sizeof(answer));
     }

     result = 0;
     for (i = 1; i <= cnt; i++)
     if  (great[i])
     {
         result += answer[i];
         result %= mod;
     }

     printf("%d\n", result);

     return 0;
}

#include <iostream>
#include <cstring>
#include <cstdio>
#define MOD 12345
using namespace std;
typedef long long ll;
struct Matrix
{
	int arr[125][125], n;
	Matrix(int _n = 0)
	{
		n = _n;
		memset(arr, 0, sizeof(arr));
	}
	inline Matrix operator *(const Matrix &a) const
	{
		Matrix res(n);
		for (int i = 0; i < n; i++)
		{
			for (int j = 0; j < n; j++)
			{
				for (int k = 0; k < n; k++)
					res.arr[i][j] = (res.arr[i][j] + arr[i][k] * a.arr[k][j]) % MOD;
			}
		}
		return res;
	}
	inline Matrix operator *=(const Matrix &a)
	{
		return *this = *this * a;
	}
};
inline Matrix quick_pow(Matrix a, ll n)
{
	Matrix res(a.n);
	res.arr[0][0] = 1;
	while (n)
	{
		if (n & 1)
			res *= a;
		a *= a;
		n >>= 1;
	}
	return res;
}
int arr[35], coef[35];
inline int gcd(int x, int y)
{
	int r;
	while (y)
	{
		r = x % y;
		x = y;
		y = r;
	}
	return x;
}
int main()
{
	// freopen("107D.in", "r", stdin);
	ll t;
	int n;
	scanf("%lld%d", &t, &n);
	for (int i = 0; i < n; i++)
	{
		char c;
		int x;
		scanf("%*c%c%d", &c, &x);
		arr[c - 'A'] = gcd(x, arr[c - 'A']);
	}
	int cur = 1;
	for (int i = 0; i < 26; i++)
	{
		if (!arr[i])
			continue;
		coef[i] = cur;
		cur *= arr[i];
	}
	Matrix mat(cur), dp(cur);
	for (int i = 0; i < cur; i++)
	{
		for (int j = 0; j < 26; j++)
		{
			if (!arr[j])
				continue;
			int x = i / coef[j] % arr[j];
			mat.arr[i][i + ((x + 1) % arr[j] - x) * coef[j]]++;
		}
	}
	printf("%d\n", quick_pow(mat, t).arr[0][0]);
	return 0;
}

//program 107D

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;

struct Matrix
{
  int Size;
  int M[200][200];
};

const int Mod=12345;

int GCD(int A,int B)
{
  return B?GCD(B,A%B):A;
}

Matrix NewMatrix(int N)
{
  Matrix T;T.Size=N;
  memset(T.M,0,sizeof(T.M));
  return T;
}

Matrix Mult(Matrix A,Matrix B)
{
  Matrix T=NewMatrix(A.Size);
  for(int k=0;k<T.Size;k++)
    for(int i=0;i<T.Size;i++)
      for(int j=0;j<T.Size;j++)
        T.M[i][j]=(T.M[i][j]+A.M[i][k]*B.M[k][j])%Mod;
  return T;
}

int main()
{
  long long K;int M;cin>>K>>M;
  vector<int> A[26],Data[26];
  while(M--)
    {
      char c=getchar();while(c<'A'||c>'Z')c=getchar();
      int X;cin>>X;A[c-65].push_back(X);
    }
  int Total=0,Size[26];
  for(int i=0;i<26;i++)
    if(A[i].size())
      {
        int T=1;
        for(int j=0;j<A[i].size();j++)
          T=T*A[i][j]/GCD(T,A[i][j]);
        Size[Total]=T;Data[Total]=A[i];Total++;
      }
  if(!Total){cout<<0<<endl;return 0;}
  int Weight[26];Weight[Total-1]=1;for(int i=Total-1;i;i--)Weight[i-1]=Weight[i]*Size[i];
  int N=Weight[0]*Size[0];
  Matrix G=NewMatrix(N);
  for(int i=0;i<N;i++)
    {
      int Tmp=i,A[26];
      for(int j=0;j<Total;j++){A[j]=Tmp/Weight[j];Tmp%=Weight[j];}
      for(int j=0;j<Total;j++)
        {
          int B[26];for(int k=0;k<Total;k++)B[k]=A[k];B[j]=(B[j]+1)%Size[j];
          int Number=0;for(int k=0;k<Total;k++)Number+=B[k]*Weight[k];
          G.M[Number][i]++;
        }
    }
  Matrix T=NewMatrix(N);for(int i=0;i<N;i++)T.M[i][i]=1;
  long long P=1;while(P*2<=K)P*=2;
  while(P){T=Mult(T,T);if(K&P)T=Mult(T,G);P/=2;}
  int Ans=0;
  for(int i=0;i<N;i++)
    {
      int Tmp=i,A[26];for(int j=0;j<Total;j++){A[j]=Tmp/Weight[j];Tmp%=Weight[j];}
      bool Flag=true;
      for(int j=0;Flag&&j<Total;j++)
        {
          Flag=false;
          for(int k=0;!Flag&&k<Data[j].size();k++)Flag=!(A[j]%Data[j][k]);
        }
      if(Flag)Ans=(Ans+T.M[i][0])%Mod;
    }
  cout<<Ans<<endl;
  return 0;
}

#include<bits/stdc++.h>
#define rep(i,l,r) for(int i=l;i<r;i++)
#define put(x) cout<<#x<<" = "<<x<<endl;
#define X first
#define Y second
#define pb push_back
#define int num
using namespace std;
typedef long long num;
typedef pair<char,int> point;
const int maxc=1000+10,inf=1e9+10,T1=123,M=12345,z=26;

int n,c;
int mat[T1][T1];
point p[maxc];
int zarib[T1][maxc],tmp[T1][T1],ans[T1][T1];
int nxt[T1][z];
bool mark[z];

void mul(int a[T1][T1],int b[T1][T1]){
	rep(i,0,T1){
		rep(j,0,T1){
			tmp[i][j]=0;
			rep(k,0,T1){
				tmp[i][j]=(tmp[i][j]+a[i][k]*b[k][j])%M;
			}
		}
	}
	rep(i,0,T1){
		rep(j,0,T1){
			ans[i][j]=tmp[i][j];
		}
	}
}

void power(int b){
	if(b==0) return;
	power(b>>1);
	mul(ans,ans);
	if(b&1){
		mul(ans,mat);
	}
}

int32_t main(){
	scanf("%lld%lld",&n,&c);
	int zr=1;
	rep(i,0,c){
		scanf(" %c%lld",&p[i].X,&p[i].Y);
		mark[p[i].X-'A']=1;
		zr*=p[i].Y;
	}
	rep(i,0,T1){
		int mask=i;
		rep(j,0,c){
			zarib[i][j]=mask%p[j].Y;
			mask/=p[j].Y;
		}
	}
	rep(ch,0,z){
		rep(i,0,zr){
			int mask=0;
			for(int j=c-1;j>=0;j--){
				mask*=p[j].Y;
				mask+=(zarib[i][j]+(p[j].X==ch+'A'))%p[j].Y;
			}
			nxt[i][ch]=mask;
		}
	}
	rep(i,0,zr){
		ans[i][i]=1;
		rep(ch,0,z){
			if(mark[ch]){
				mat[i][nxt[i][ch]]=(mat[i][nxt[i][ch]]+1)%M;
			}
		}
	}
	power(n);
	int sum=0;
	rep(i,0,zr){
		int mn[z];
		fill(mn,mn+z,inf);
		rep(j,0,c){
			mn[p[j].X-'A']=min(mn[p[j].X-'A'],zarib[i][j]);
		}
		bool ok=1;
		rep(ch,0,z){
			if(mark[ch]==1 && mn[ch]>0){
				ok=0;
			}
		}
		if(ok){
			sum=(sum+ans[0][i]);
		}
	}
	printf("%lld\n",sum);
}

#include <ctype.h>
#include <math.h>
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <iostream>
#include <complex>
#include <map>
#include <set>
#include <string>
#include <vector>
using namespace std;

const int MAXNUM = 123, MOD = 12345;

typedef int Mat[MAXNUM][MAXNUM];

Mat base, ret;
bool hash[26][MAXNUM + 1];
vector<int> l[MAXNUM], b;
int ans = 0;
long long n;

void mul(Mat a, Mat b, Mat c, int n) {
  static Mat tmp;
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      tmp[i][j] = 0;
      for (int k = 0; k < n; ++k) {
        tmp[i][j] = (tmp[i][j] + b[i][k] * c[k][j]) % MOD;
      }
    }
  }
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      a[i][j] = tmp[i][j];
    }
  }
}

void pow(long long b, int n) {
  for (int i = 0; i < n; ++i) {
    for (int j = 0; j < n; ++j) {
      ret[i][j] = i == j;
    }
  }
  while (b) {
    if (b & 1) mul(ret, ret, base, n);
    mul(base, base, base, n);
    b >>= 1;
  }
}

void dfs(int step, int begin, int kind) {
  if (step == 26) {
    if (b.size() & 1) kind = -kind;
    static int x[26], y[26];
    int tot = 1;
    for (size_t i = 0; i < b.size(); ++i) {
      tot *= b[i];
    }
    for (int i = 0; i < tot; ++i) {
      for (int j = 0; j < tot; ++j) {
        base[i][j] = 0;
      }
    }
    for (int i = 0; i < tot; ++i) {
      int t = i;
      for (size_t j = 0; j < b.size(); ++j) {
        x[j] = t % b[j];
        t /= b[j];
      }
      for (size_t j = 0; j < b.size(); ++j) {
        memcpy(y, x, sizeof(x));
        y[j] = (y[j] + 1) % b[j];
        int to = 0;
        for (int k = b.size() - 1; k >= 0; --k) {
          to = to * b[k] + y[k];
        }
        ++base[i][to];
      }
    }
    pow(n, tot);
    ans = (ans + kind * ret[0][0] + MOD) % MOD;
    return;
  }
  if (l[step].size() == 0u) {
    dfs(step + 1, 0, kind);
  } else {
    for (size_t i = begin; i < l[step].size(); ++i) {
      if (begin == 0) {
        b.push_back(l[step][i]);
        dfs(step, i + 1, -kind);
        dfs(step + 1, 0, -kind);
        b.pop_back();
      } else {
        b.back() *= l[step][i];
        dfs(step, i + 1, -kind);
        dfs(step + 1, 0, -kind);
        b.back() /= l[step][i];
      }
    }
  }
}

int main() {
  int m, x;
  char ch;
  scanf("%lld%d", &n, &m);
  for (int i = 0; i < m; ++i) {
    scanf(" %c%d", &ch, &x);
    hash[ch - 'A'][x] = true;
  }
  for (int i = 0; i < 26; ++i) {
    for (int j = 1; j <= MAXNUM; ++j) {
      if (!hash[i][j]) continue;
      l[i].push_back(j);
      for (int k = j + j; k <= MAXNUM; k += j) {
        hash[i][k] = false;
      }
    }
  }
  dfs(0, 0, 1);
  printf("%d\n", ans);
  return 0;
}

#include <cstdio>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#include <set>
#include <map>
using namespace std;
const int MOD = 12345;
const int STD_SIZE = 130;
int msize;
struct Matrix {
    int mat[STD_SIZE][STD_SIZE];
    Matrix () {memset(mat, 0, sizeof mat);}
    inline Matrix operator * (const Matrix & b) {
        Matrix ret;
        for(int i = 0; i<msize; i++)
            for(int j = 0; j<msize; j++)
                for(int k = 0; k<msize; k++)
                    ret.mat[i][j] = (ret.mat[i][j]+mat[i][k]*b.mat[k][j])%MOD;
        return ret;
    }
};
typedef long long LL;
map<char, vector<int> > mp;
int lvl[30], prd[30];
bool vis[STD_SIZE], nvalid[STD_SIZE];
int main () {
    LL N; int C;
    cin >> N;
    scanf("%d", &C);
    for(int i = 1; i<=C; i++) {
        char buf[10]; int val;
        scanf("%s%d", buf, &val);
        mp[buf[0]].push_back(val);
    }
    for(char chr = 'A'; chr <= 'Z'; chr++) {
        vector<int>&tmp = mp[chr];
        sort(tmp.begin(), tmp.end());
        tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
        lvl[chr-'A'+1] = 1;
        for(int i = 0; i<(int)tmp.size(); i++)
            lvl[chr-'A'+1] = lvl[chr-'A'+1]*tmp[i];
    }
    prd[0] = lvl[0] = 1;
    for(int i = 1; i<=26; i++)
        prd[i] = prd[i-1]*lvl[i];
    msize = prd[26];
    Matrix unit, mfac;
    for(int i = 0; i<msize; i++) unit.mat[i][i] = 1;
    for(int cur = 0; cur<msize; cur++) {
        for(int nxt = 0; nxt<26; nxt++) {
            if(mp['A'+nxt].size() == 0) continue ;
            int cbit = cur/prd[nxt]%lvl[nxt+1];
            int nbit = (cbit+1)%lvl[nxt+1];
            int delta = (nbit-cbit)*prd[nxt];
            mfac.mat[cur][cur+delta] ++;
        }
    }
    while(N) {
        if(N&1) unit = unit*mfac;
        mfac = mfac*mfac;
        N >>= 1;
    }
    int ans = 0;
    for(int chr = 0; chr<26; chr++) {
        vector<int>&tmp = mp['A'+chr];
        if(tmp.size() == 0) continue ;
        memset(vis, 0, sizeof vis);
        for(int i = 0; i<(int)tmp.size(); i++)
            for(int j = 0; j<lvl[1+chr]; j+=tmp[i])
                vis[j] = true;
        for(int i = 0; i<msize; i++) {
            int cbit = i/prd[chr]%lvl[chr+1];
            if(!vis[cbit]) nvalid[i] = true;
        }
    }
    for(int i = 0; i<msize; i++) {
        if(nvalid[i]) continue ;
        ans = (ans+unit.mat[0][i]);
    }
    cout << ans << '\n';
}
/*
11 2
A 6
B 2
*/

/*
 * 2011-08-23  Martin  <Martin@Martin-desktop>

 *
 */
#include <algorithm>
#include <iostream>
#include <fstream>
#include <climits>
#include <vector>

using namespace std;

#define tr(i, x) for (typeof(x.begin()) i = x.begin(); i != x.end(); ++ i)
#define rep(i, n) for (int i = 0; i < n; ++ i)
#define pii pair <int, int>
#define mp make_pair
#define x first
#define y second
#define pb push_back
#define ll long long

#define CharSet 26
#define Mod 12345

class Matrix: public vector < vector <int> >
{
	private:
		Matrix(int n, vector <int> a)
		{
			this->clear();
			rep (i, n)
				pb(a);
		}
	public:
		Matrix()
		{
			this->clear();
		}
		Matrix(int n, int m)
		{
			this->clear();
			*this = Zero(n, m);
		}
		Matrix Zero(int n, int m)
		{
			return Matrix (n, vector <int> (m, 0));
		}
		Matrix One(int n)
		{
			Matrix res(n, n);
			rep (i, n)
				res[i][i] = 1;
			return res;
		}
		Matrix operator * (const Matrix &b)
		{
			Matrix c;
			if (rows() == b.lines())
			{
				int u = lines();
				int v = rows();
				int w = b.rows();
				c = Zero(u, w);
				rep (i, u)
					rep (j, v)
						rep (k, w)
						{
							c[i][k] += (*this)[i][j] * b[j][k];
							c[i][k] %= Mod;
						}
			}
			else
				cerr << "error occurred at " << __LINE__ << endl;
			return c;
		}
		Matrix pow(unsigned ll n)
		{
			Matrix res;
			if (lines() == rows())
			{
				int l = lines();
				res = res.One(l);
				Matrix tmp(*this);
				for (int i = 0; n >> i; ++ i)
				{
					if (n & (1ULL << i))
						res = res * tmp;
					tmp = tmp * tmp;
				}
			}
			else
				cerr << "error occurred at " << __LINE__ << endl;
			return res;
		}
		size_type lines() const
		{
			return size();
		}
		size_type rows() const
		{
			return (size() == 0) ? 0 : (*this)[0].size();
		}
};

ll N;
int C;
bool Appear[CharSet];

int main()
{
	cin >> N >> C;
	fill(Appear, Appear + CharSet, 0);
	vector <pii> cd;
	cd.clear();
	rep (i, C)
	{
		char Ch;
		int t;
		cin >> Ch >> t;
		Appear[Ch - 'A'] = 1;
		if (t != 1)
			cd.pb(mp(Ch - 'A', t));
	}
	vector <int> pd;
	pd.clear();
	int cds = cd.size();
	pd.pb(1);
	rep (i, cds)
		pd.pb(pd.back() * cd[i].y);
	int matsize = pd.back();
	Matrix mat(matsize, matsize);
	rep (i, matsize)
	{
		rep (ch, 26)
			if (Appear[ch])
			{
				int target = i;
				rep (k, cds)
					if (cd[k].x == ch)
					{
						if ((target % pd[k + 1]) / pd[k] == cd[k].y - 1)
							target -= (cd[k].y - 1) * pd[k];
						else
							target += pd[k];
					}
				++ mat[i][target];
			}
	}
	mat = mat.pow(N);
	ll ans = 0;
	rep (i, matsize)
	{
		bool Flag = 1;
		rep (ch, 26)
			if (Appear[ch])
			{
				bool Satisfy = 0;
				bool Exist = 0;
				rep (k, cds)
					if (cd[k].x == ch)
					{
						Exist = 1;
						if ((i % pd[k + 1]) / pd[k] == 0)
							Satisfy = 1;
					}
				if (Exist && !Satisfy)
				{
					Flag = 0;
					break;
				}
			}
		if (Flag)
			ans = (ans + mat[0][i]) % Mod;
	}
	cout << ans << endl;
	return 0;
}

#include <iomanip>
#include <ctime>
#include <numeric>
#include <functional>
#include <iostream>
#include <vector>
#include <algorithm>
#include <string>
#include <cstring>
#include <climits>
#include <cmath>
#include <cctype>
#include <sstream>
#include <map>
#include <set>
#include <cstdio>
#include <queue>
#define f(i,x,y) for(int i=x;i<y;i++)
#define fd(i,y,x) for(int i=y;i>=x;i--)
#define FOR(it,A) for( typeof A.begin() it = A.begin(); it!=A.end(); it++)
#define impr(A) for( typeof A.begin() chen = A.begin(); chen !=A.end(); chen++ ) cout<<*chen<<" "; cout<<endl
#define ll long long
#define vint vector<int>
#define clr(A,x) memset(A,x,sizeof(A))
#define CLR(v) f(i,0,n) v[i].clear()
#define oo (1<<30)
#define ones(x) __builtin_popcount(x)
#define all(v) (v).begin(),(v).end()
#define rall(v) (v).rbegin(),(v).rend()
#define pb push_back
#define eps (1e-9)
#define cua(x) (x)*(x)
#define MAX 1000000
using namespace std;

int tam, mod = 12345;
void mmul (ll A[128][128], ll B[128][128], ll M[128][128]){
	ll C[128][128];
	f(i,0,tam)f(k,0,tam){
		ll res = 0;
		f(j,0,tam) res += A[i][j] * B[j][k];
		C[i][k] = res%mod;
	}
	//f(i,0,tam){ f(j,0,tam) cout << A[i][j]; cout << endl; }
	//f(i,0,tam){ f(j,0,tam) cout << B[i][j]; cout << endl; }
	//f(i,0,tam){ f(j,0,tam) cout << C[i][j]; cout << endl; }
	//cout << endl;
	f(i,0,tam)f(j,0,tam) M[i][j] = C[i][j];
}
void mpow (ll A[128][128], ll pot, ll P[128][128]){
	ll T[128][128];
	f(i,0,tam)f(j,0,tam) T[i][j] = A[i][j];
	f(i,0,tam)f(j,0,tam) P[i][j] = 0;
	f(i,0,tam) P[i][i] = 1;

	while( pot ){
		if( pot&1 ) mmul (P, T, P);
		mmul (T, T, T);
		pot >>= 1;
	}
}

ll A[128][128], P[128][128];

int mul[30]; int sz; int M;

int code(vint &v){
	int res = 0;
	f(j,0,sz) res = res*mul[j] + v[j];
	return res;
}
vint decode(int x){
	vint v(sz,0);
	fd(i,sz-1,0){
		v[i] = x%mul[i];
		x/= mul[i];
	}
	return v;
}

int main()
{
	/*sz = 0;
	mul[sz++] = 1; mul[sz++] = 2; mul[sz++] = 3;
	M = 1; f(i,0,sz) M *= mul[i];
	cout << M << endl;

	clr(A,0);
	f(i,0,M){
		vint v = decode(i);
		f(j,0,sz){
			v[j]--; if( v[j]<0 ) v[j] += mul[j];
			int k = code(v); A[i][k]++;
			v[j]++; if( v[j]==mul[j] ) v[j] = 0;
		}
	}
	f(i,0,M){ f(j,0,M) cout<<A[i][j]; cout << endl; }
	tam = M;
	f(n,1,10){
		mpow (A, n, P);
		cout << P[0][0] << endl;
	}
	return 0;
	cin >> M;
	return 0;
	*/

	int n,c; int x[30][128]; char cc; int k;
	int vis[30];
	clr(x,0);
	clr(vis,0);
	cin >> n >> c;
	f(i,0,c){
		cin >> cc >> k;
		x[cc-'A'][k] = 1;
	}
	sz = 0; M = 1;
	f(i,0,26){
		vis[i] = 0; int prod = 1;
		f(j,0,128) if( x[i][j] ) vis[i] = 1, prod *= j;
		if( vis[i] ) mul[sz++] = prod, M*= prod;
	}
	clr(A,0);
	f(i,0,M){
		vint v = decode(i);
		f(j,0,sz){
			v[j]--; if( v[j]<0 ) v[j] += mul[j];
			int k = code(v); A[i][k]++;
			v[j]++; if( v[j]==mul[j] ) v[j] = 0;
		}
	}
	tam = M;
	mpow (A, n, P);
	ll res = 0;
	f(i,0,M){
		vint v = decode(i);
		bool todos = 1;
		f(j,0,sz){
			bool ok = 0;
			f(k,0,128)if( x[j][k] && v[j]%k==0 ) ok = 1;
			if( ok==0 ) todos = 0;
		}
		if( todos ) res += P[i][0];
	}
	cout << res << endl;
	//f(i,0,M){ f(j,0,M) cout << P[i][j]; cout << endl; }
	//f(i,0,M) cout << P[i][0]<<" "; cout << endl;
}

#include <iostream>
#include <fstream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#include <ctime>
#include <algorithm>
#include <map>
#include <queue>
#include <vector>
using namespace std;
#define mod 12345

int total, cnt, f[66][205][205], answer[205], news[205], sum[1050], mul[1050];
char dif[205], ch[1050];
bool great[1050], can[1050][205];
vector <int> doing;
map <vector <int>, int> number;

int  Rand()
{
     return (rand() << 15) | rand();
}

void DFS(int current)
{
int  i, size;
bool solved;

     if  (current > total)
     {
         number[doing] = ++cnt;
         size = doing.size();
         solved = true;
         for (i = 0; i < size; i++)
         if  (!can[dif[i + 1]][doing[i]])
         {
             solved = false;
             break;
         }
         if  (solved)
         {
             great[cnt] = true;
         }

         return;
     }
     for (i = 0; i < sum[dif[current]]; i++)
     {
         doing.push_back(i);
         DFS(current + 1);
         doing.pop_back();
     }

     return;
}

int  main()
{
int  all, i, j, k, times, Log, result, current, next, size, temp;
long long n;
vector <int> vec;
map  <vector <int>, int> :: iterator it, it2;

//     freopen("d.in", "r", stdin);
//     freopen("d.out", "w", stdout);

     srand((unsigned) time (0));

     for (i = 'A'; i <= 'Z'; i++)
     {
         sum[i] = 1;
     }

     scanf("%I64d%d\n", &n, &all);
     if  (n == 0 || all == 0)
     {
         printf("1\n");

         return 0;
     }
     total = 0;
     for (i = 1; i <= all; i++)
     {
         scanf("%c%d\n", &ch[i], &mul[i]);
         sum[ch[i]] *= mul[i];
         dif[++total] = ch[i];
     }

     sort(dif + 1, dif + total + 1);
     for (i = j = 1; i < total; i++)
     if  (dif[i + 1] != dif[j])
     {
         dif[++j] = dif[i + 1];
     }
     total = j;

     for (i = 1; i <= all; i++)
     {
         for (j = 0; j < sum[ch[i]]; j += mul[i])
         {
             can[ch[i]][j] = true;
         }
     }

     doing.clear();
     cnt = 0;
     DFS(1);

     for (it = number.begin(); it != number.end(); it++)
     {
         current = it -> second;
         vec = it -> first;
         size = vec.size();
         for (i = 0; i < size; i++)
         {
             temp = vec[i];
             vec[i] = (vec[i] + 1) % sum[dif[i + 1]];
             it2 = number.find(vec);
             next = it2 -> second;
             f[0][current][next]++;
             vec[i] = temp;
         }
     }

     Log = (int) (log2(n));
     for (times = 1; times <= Log; times++)
     {
         for (i = 1; i <= cnt; i++)
         {
             for (j = 1; j <= cnt; j++)
             {
                 for (k = 1; k <= cnt; k++)
                 {
                     f[times][i][j] += f[times - 1][i][k] * f[times - 1][k][j];
                     f[times][i][j] %= mod;
                 }
             }
         }
     }

     answer[1] = 1;
     for (times = Log; times >= 0; times--)
     if  ((1ll << times) <= n)
     {
         n -= 1ll << times;
         memset(news, 0, sizeof(news));
         for (i = 1; i <= cnt; i++)
         {
             for (j = 1; j <= cnt; j++)
             {
                 news[i] += f[times][i][j] * answer[j];
                 news[i] %= mod;
             }
         }
         memcpy(answer, news, sizeof(answer));
     }

     result = 0;
     for (i = 1; i <= cnt; i++)
     if  (great[i])
     {
         result += answer[i];
         result %= mod;
     }

     printf("%d\n", result);

     return 0;
}

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>

using namespace std;

const int MOD = 12345;

int GCD(int a, int b)
{
	while(a > 0)
	{
		if(a < b)
			swap(a, b);
		a %= b;
	}
	return b;
}

int LCM(int a, int b)
{
	if(a * b == 0)
		return max(a, b);
	return a * b / GCD(a, b);
}

vector <int> arr, now;
map <vector <int>, int> b;

void Fill(int n)
{
	if(n == arr.size())
	{
		int t = b.size();
		b[now] = t;
		return;
	}
	for(int i = 0; i < arr[n]; i++)
	{
		now[n] = i;
		Fill(n + 1);
	}
}

struct M
{
	int arr[130][130];
	M()
	{
		memset(arr, 0, sizeof(arr));
	}
	M& operator =(const M &a)
	{
		memcpy(arr, a.arr, sizeof(arr));
		return *this;
	}
	M operator * (const M &a)
	{
		M ans;
		for(int i = 0; i < 130; i++)
			for(int j = 0; j < 130; j++)
				for(int k = 0; k < 130; k++)
				{
					ans.arr[i][j] += arr[i][k] * a.arr[k][j];
					ans.arr[i][j] %= MOD;
				}
		return ans;
	}
};

M E()
{
	M ans;
	for(int i = 0; i < 130; i++)
		ans.arr[i][i] = 1;
	return ans;
}

M gr, a;

vector <vector <int> > dd, d;
vector <bool> f;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#endif
	long long n;
	int m;
	cin >> n >> m;
	vector <int> tmp(26, 0);
	dd.resize(26);
	for(int i = 0; i < m; i++)
	{
		char c;
		int x;
		cin >> c >> x;
		tmp[c - 'A'] = LCM(tmp[c - 'A'], x);
		dd[c - 'A'].push_back(x);
	}

	for(int i = 0; i < m; i++)
		if(tmp[i] != 0)
		{
			arr.push_back(tmp[i]);
			d.push_back(dd[i]);
		}
	now.resize(arr.size());
	Fill(0);
	if(b.size() > 130)
		throw(0);
	f.assign(b.size(), true);
	for(map <vector <int>, int>::iterator it = b.begin(); it != b.end(); it++)
	{
		vector <int> now = it->first;
		for(int i = 0; i < now.size(); i++)
		{
			bool ok = false;
			for(int j = 0; j < d[i].size(); j++)
				if(now[i] % d[i][j] == 0)
					ok = true;
			if(!ok)
				f[it->second] = false;
		}
		for(int i = 0; i < now.size(); i++)
		{
			vector <int> tmp = now;
			tmp[i]++;
			tmp[i] %= arr[i];
			gr.arr[b[now]][b[tmp]]++;
			gr.arr[b[now]][b[tmp]] %= MOD;
		}
	}
	a = gr;
	gr = E();
	while(n > 0)
	{
		if(n % 2 == 1)
		{
			gr = gr * a;
			n--;
		}
		else
		{
			a = a * a;
			n /= 2;
		}
	}
	int ans = 0;
	for(int i = 0; i < b.size(); i++)
		if(f[i])
		{
			ans += gr.arr[0][i];
			ans %= MOD;
		}
	cout << ans << endl;
	return 0;
}

//program 107D

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<vector>

using namespace std;

struct Matrix
{
  int Size;
  int M[200][200];
};

const int Mod=12345;

int GCD(int A,int B)
{
  return B?GCD(B,A%B):A;
}

Matrix NewMatrix(int N)
{
  Matrix T;T.Size=N;
  memset(T.M,0,sizeof(T.M));
  return T;
}

Matrix Mult(Matrix A,Matrix B)
{
  Matrix T=NewMatrix(A.Size);
  for(int k=0;k<T.Size;k++)
    for(int i=0;i<T.Size;i++)
      for(int j=0;j<T.Size;j++)
        T.M[i][j]=(T.M[i][j]+A.M[i][k]*B.M[k][j])%Mod;
  return T;
}

int main()
{
  long long K;int M;cin>>K>>M;
  vector<int> A[26],Data[26];
  while(M--)
    {
      char c=getchar();while(c<'A'||c>'Z')c=getchar();
      int X;cin>>X;A[c-65].push_back(X);
    }
  int Total=0,Size[26];
  for(int i=0;i<26;i++)
    if(A[i].size())
      {
        int T=1;
        for(int j=0;j<A[i].size();j++)
          T=T*A[i][j]/GCD(T,A[i][j]);
        Size[Total]=T;Data[Total]=A[i];Total++;
      }
  int Weight[26];Weight[Total-1]=1;for(int i=Total-1;i;i--)Weight[i-1]=Weight[i]*Size[i];
  int N=Weight[0]*Size[0];
  Matrix G=NewMatrix(N);
  for(int i=0;i<N;i++)
    {
      int Tmp=i,A[26];
      for(int j=0;j<Total;j++){A[j]=Tmp/Weight[j];Tmp%=Weight[j];}
      for(int j=0;j<Total;j++)
        {
          int B[26];for(int k=0;k<Total;k++)B[k]=A[k];B[j]=(B[j]+1)%Size[j];
          int Number=0;for(int k=0;k<Total;k++)Number+=B[k]*Weight[k];
          G.M[Number][i]=1;
        }
    }
  Matrix T=NewMatrix(N);for(int i=0;i<N;i++)T.M[i][i]=1;
  long long P=1;while(P*2<=K)P*=2;
  while(P){T=Mult(T,T);if(K&P)T=Mult(T,G);P/=2;}
  int Ans=0;
  for(int i=0;i<N;i++)
    {
      int Tmp=i,A[26];for(int j=0;j<Total;j++){A[j]=Tmp/Weight[j];Tmp%=Weight[j];}
      bool Flag=true;
      for(int j=0;Flag&&j<Total;j++)
        {
          Flag=false;
          for(int k=0;!Flag&&k<Data[j].size();k++)Flag=!(A[j]%Data[j][k]);
        }
      if(Flag)Ans=(Ans+T.M[i][0])%Mod;
    }
  cout<<Ans<<endl;
  return 0;
}

#include <cstdio>
#include <vector>
#include <map>
#include <cstring>
using namespace std;
const int mod=12345;
typedef long long LL;
int N;

struct Mat{
	int v[150][150];
	int* operator [](int id){
		return v[id];
	}
} mat;
Mat operator *(Mat& a,Mat &b){
	Mat c;
	memset(&c,0,sizeof(c));
	for(int i = 0; i < N; i++)
		for(int j = 0; j < N; j++)
			for(int k = 0; k < N; k++)
				c[i][j]=(c[i][j] + a[i][k] * b[k][j])%mod;
	return c;
}
map<vector<int>,int> m;
bool in[100], allow[100][150],ans[150];
int _lcm[100],cnt;
LL n;
int initMat(const vector<int>& v){
	map<vector<int>,int>::iterator it = m.find(v);

	if (it != m.end())
		return it->second;
	int id = N++;
	ans[id] = true;
	for (int i = 0; i < 26; i++)
		if (in[i]) {
			vector<int> _next(v);
			_next[i] = (_next[i] + 1) % _lcm[i];
			mat[id][initMat(_next)]++;
		}

	for (int i = 0; i < 26; i++)
		ans[id] = in[i] && ans[id] && allow[i][v[i]];

	m.insert(make_pair(v,id));
	return id;
}
int gcd(int x,int y){
	return y?gcd(y,x%y):x;
}int lcm(int x,int y){
	return ((LL)x*y)/gcd(x,y);
}
int main(){
	freopen("D.in","r",stdin);
	scanf("%I64d%d",&n,&cnt);
	for(int i = 1; i <= cnt; i++){
		char tmp[5];int x = 0;
		scanf("%s%d",tmp,&x);
		allow[tmp[0]-'A'][x] = true;
		in[tmp[0]-'A'] = true;
	}

	for(int i = 0; i<26;i++){
		_lcm[i]=1;
		for(int j = 1; j < 123; j++)
			if(allow[i][j])
				_lcm[i] = lcm(_lcm[i],j);

		for(int j = 122; j > 0; j--)
			if(allow[i][j])
				for(int k = j; k < 123; k += j)
					allow[i][k]=true;
		allow[i][0] = true;
	}

	initMat(vector<int>(26));
	Mat res;
	memset(&res,0,sizeof(res));
	for(int i = 0; i < 130; i++)
		res[i][i] = 1;
	for(int i = 63; i >= 0; i--){
		res=res * res;
		if((n>>i)&1)
			res = res * mat;
	}
	int Ans = 0;
	for(int i = 0; i < N; i++)
		if(ans[i])
			Ans=(Ans + res[0][i]) % mod;
	printf("%d\n",Ans);
}

#include <cstring>
#include <cstdio>
#include <iostream>
using namespace std;

typedef int matrix[140][140];
const int modp=12345;

int k,N,mod[30],base[30],cnt[30],num[30][30];
int legal[140],ans;
long long n;
matrix a,b;

void mul(matrix a, matrix b)
{
	matrix c;
	for (int i=0; i<N; i++)
	for (int j=0; j<N; j++)
		c[i][j]=0;

	for (int i=0; i<N; i++)
	for (int j=0; j<N; j++)
	for (int k=0; k<N; k++)
		c[i][j]=(c[i][j]+a[i][k]*b[k][j])%modp;

	for (int i=0; i<N; i++)
	for (int j=0; j<N; j++)
		a[i][j]=c[i][j];
}

int gcd(int x, int y)
{
	if (y==0) return x;
	return gcd(y,x%y);
}

int main()
{
	cin>>n>>k;
	for (int i=0; i<26; i++) mod[i]=1;
	for (int i=1; i<=k; i++)
	{
		char type[4]; int p,x;
		scanf("%s",type); p=type[0]-'A';
		scanf("%d",&x); mod[p]*=x/gcd(x,mod[p]);
		cnt[p]++; num[p][cnt[p]]=x;
	}
	base[0]=1;
	for (int i=0; i<26; i++) base[i+1]=base[i]*mod[i];
	N=base[26];

	for (int i=0; i<N; i++)
	{
		legal[i]=1;
		for (int j=0; j<26; j++)
		if (cnt[j])
		{
			int res=0, zt;
			zt=i+base[j];
			if ((i/base[j]+1)%mod[j]==0) zt-=base[j+1]; b[i][zt]++;
			for (int k=1; k<=cnt[j]; k++)
				if (i%num[j][k]==0) res=1;
			legal[i]&=res;
		}
	}

	a[0][0]=1;
	for (;n;n>>=1)
	{
		if (n&1) mul(a,b);
		mul(b,b);
	}
	for (int i=0; i<N; i++) if (legal[i]) ans=(ans+a[0][i])%modp;
	cout<<ans<<endl;
	//for (;;);
}

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
const int N = 505, oo = 12345;
int m, x, y, now, ans, a[N][N], b[N][N], c[N], e[N], s[N], res[N];
bool d[N][N], f[N];
char type[5];
vector<int> p(26);
map<vector<int>, int> h;
void mul1()
{
    memset(c, 0, sizeof(c));
    for (int i = 0; i < now; i++)
        for (int j = 0; j < now; j++)
            c[i] = (a[i][j] * res[j] + c[i]) % oo;
    memcpy(res, c, sizeof(res));
}
void mul()
{
    memset(b, 0, sizeof(b));
    for (int i = 0; i < now; i++)
        for (int j = 0; j < now; j++)
            for (int k = 0; k < now; k++)
                b[i][j]+=a[i][k] * a[k][j] + b[i][j];
    for (int i = 0; i < now; i++)
        for (int j = 0; j < now; j++)b[i][j]%=oo;
    memcpy(a, b, sizeof(a));
}
int dfs(vector<int> c)
{
    typeof(h.end()) it = h.find(c);
    if (it != h.end()) return it->second;
    int tmp = now++;
    h[c] = tmp;
    f[tmp] = 1;
    vector<int > b;
    for (int i = 0; i < 26; i++) if (e[i]) f[tmp] &= d[i][c[i]];
    for (int i = 0; i < 26; i++) if (e[i]) b = c, b[i] = (b[i] + 1) % s[i], a[dfs(b)][tmp]++;
    return tmp;
}
int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}
int main()
{
    long long n;
    cin >> n >> m, res[0] = 1;
    for (int i = 1; i <= m; i++) scanf("%s%d", type, &y), x = type[0] - 65, d[x][y] = 1, e[x] = 1;
    for (int i = 0; i < 26; i++)
    {
        s[i] = 1;
        for (int j = 0; j < 123; j++) if (d[i][j]) s[i] *= j / gcd(s[i], j);
        for (int j = 122; j; j--) if (d[i][j])
                for (int k = j; k < 123; k += j) d[i][k] = 1;
        d[i][0] = 1;
    }
    dfs(p);
    while (n)
    {
        if (n & 1) mul1();
        n /= 2;
        mul();
    }
    for (int i = 0; i < now; i++) if (f[i]) ans = (ans + res[i]) % oo;
    printf("%d\n", ans);
    return 0;
}

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

using namespace std;
const int MaxP=12345;
typedef long long LL;
int T,i,j,c,x[1010],w[26],s[200][26];
LL n;
char C[1010];
bool v[26];

struct Matrix{
  int M[124][124];
  Matrix operator *(const Matrix a) const {
    Matrix b;
    memset(b.M,0,sizeof(b.M));
    for (int i=0;i<T;i++)
      for (int j=0;j<T;j++)
        for (int k=0;k<T;k++)
          b.M[i][j]=(b.M[i][j]+M[i][k]*a.M[k][j])%MaxP;
    return b;
  }
} A,B;

void calc(){
  T=1;
  for (i=0;i<26;i++)
    if (w[i]>0) T*=w[i];
  for (i=1;i<T;i++){
    memcpy(s[i],s[i-1],sizeof(s[i]));
    s[i][25]=s[i-1][25]+1;
    for (j=25;j>-1;j--)
    if (s[i][j]>=w[j]){
      s[i][j]=0;
      s[i][j-1]++;
    } else break;
  }
}

bool pd(int x,int y){
  bool flag=0,g=0;
  for (int i=0;i<26;i++){
    if (w[i]==1) g=1;
    if (w[i]>1 && ((s[y][i]+1)%w[i]==s[x][i])){
      if (flag) return 0;
      flag=1;continue;
    }
    if (s[x][i]!=s[y][i]) return 0;
  }
  return flag || g;
}

void Make_Matrix(){
  for (i=0;i<T;i++)
    for (j=0;j<T;j++)
      if (pd(i,j)) A.M[i][j]=1;
        else A.M[i][j]=0;
}

void Qck(LL n){
  if (n==1){
    B=A;
    return;
  }
  Qck(n>>1);
  B=B*B;
  if (n&1) B=B*A;
}

bool PD(int X){
  memset(v,0,sizeof(v));
  for (int i=1;i<=c;i++)
    if (s[X][C[i]-'A']%x[i]==0) v[C[i]-'A']=1;
  for (int i=0;i<26;i++) if (!v[i] && w[i]>0) return 0;
  return 1;
}

int ANS(){
  int ret=0;
  for (i=0;i<T;i++)
    if (PD(i)) ret+=B.M[i][0];
  return ret;
}

int main(){
  scanf("%I64d%d\n",&n,&c);
  for (i=1;i<=c;i++){
    C[i]=getchar();
    scanf("%d\n",x+i);
    if (w[C[i]-'A']==0) w[C[i]-'A']=x[i];
      else w[C[i]-'A']*=x[i];
  }
  if (!n){
    printf("%d\n",1);
    return 0;
  }
  calc();
  Make_Matrix();
  Qck(n);
  printf("%d\n",ANS());
  return 0;
}

#include<iostream>
#include<cstdio>
#include<vector>
#define mod 12345
using namespace std;
long long res;
struct node
{
  long long W[123];
};
node c,ans,tans,e,w[123];
long long MOD;
node operator * (node a,node b)
{
  for (int i=0;i<res;++i)
    c.W[i]=0;
  for (int i=0;i<res;++i)
    for (int j=0;j<res;++j)
      c.W[(i+j)%res]=(c.W[(i+j)%res]+a.W[i]*b.W[j]%MOD)%MOD;
  return c;
}
node operator + (node a,node b)
{
  for (int i=0;i<res;++i)
    c.W[i]=(a.W[i]+b.W[i])%MOD;
  return c;
}
node operator - (node a,node b)
{
  for (int i=0;i<res;++i)
    c.W[i]=(a.W[i]-b.W[i])%MOD;
  return c;
}
node fast_pow(node a,long long b)
{
  if (b==0)
    return e;
  if (b&1)
    return fast_pow(a*a,b/2)*a;
  else
    return fast_pow(a*a,b/2);
}
char x;
long long n,C,y,dp[27][124],F[27][124],cnt[27];
vector<int>p[28];
int read()
{
  char c=0;
  int sum=0;
  while (c<'0'||c>'9')
    c=getchar();
  while ('0'<=c&&c<='9')
    sum=sum*10+c-'0',c=getchar();
  return sum;
}
int gcd(int x,int y)
{
  if (y==0)
    return x;
  return gcd(y,x%y);
}
int lcm(int x,int y)
{
  return x*y/gcd(x,y);
}
node tmp;
void dfs(int t,long long mul)
{
  if (t==27)
    {
      tmp=fast_pow(tans,n);
      for (int i=0;i<res;++i)
	tmp.W[i]=tmp.W[i]*mul%MOD;
      ans=ans+tmp;
      return;
    }
  if (!p[t].size())
    {
      dfs(t+1,mul);
      return;
    }
  for (int i=0;i<123;++i)
    if (F[t][i])
      tans=tans+w[i],dfs(t+1,mul*F[t][i]%MOD),tans=tans-w[i];
  return;
}
int main()
{
  n=read(),C=read();
  res=1;
  for (int i=1;i<=C;++i)
    {
      cin>>x,y=read();
      p[x-'A'].push_back(y),res=lcm(res,y);
    }
  e.W[0]=1;
  for (int i=0;i<res;++i)
    w[i].W[i]=1;
  MOD=mod;
  for (int i=0;i<26;++i)
    {
      cnt[i]=1;
      for (int j=0;j<p[i].size();++j)
	cnt[i]=lcm(cnt[i],p[i][j]);
      MOD*=cnt[i];
    }
  for (int i=0;i<26;++i)
    if (p[i].size())
      {
	dp[i][1]=-1;
	for (int j=0;j<p[i].size();++j)
	  for (int s=res;s>=1;--s)
	    dp[i][lcm(s,p[i][j])]-=dp[i][s];
	dp[i][1]++;
	for (int s=1;s<=res;++s)
	  if (cnt[i]%s==0)
	    {
	      for (int t=0;t<res;t+=res/s)
		F[i][t]=(F[i][t]+dp[i][s]*(cnt[i]/s)%MOD)%MOD;
	    }
      }
  dfs(0,1);
  int ts;
  for (int i=1;i<res;++i)
    if (res%i==0)
      {
	ts=ans.W[i];
	for (int j=0;j<res;j+=i)
	  ans.W[j]=(ans.W[j]-ts)%MOD;
      }
  ans.W[0]=(ans.W[0]+MOD)%MOD;
  for (int i=0;i<26;++i)
     ans.W[0]/=cnt[i];
  printf("%lld\n",(ans.W[0]+mod)%mod);
  return 0;
}

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <map>
#include <vector>
using namespace std;

#define M 1005
#define mod 12345
#define LL long long

struct node {
    bool v[30];
    bool operator < (const node& rhs) const{
        for (int i = 1; i <= 26; i ++){
            if (v[i] == rhs.v[i])
                continue;
            return v[i] < rhs.v[i];
        }
        return 0;
    }
}prepare;
struct edge {
    int r, c;
    LL jz[125][125];
    edge operator * (const edge& rhs) const{
        edge ans;
        ans.r = r, ans.c = rhs.c;
        for (register int i = 0; i <= ans.r; i ++)
            for (register int j = 0; j <= ans.c; j ++)
                ans.jz[i][j] = 0;
        for (register int i = 1; i <= r; i ++)
            for (register int j = 1; j <= rhs.c; j ++)
                for (register int k = 1; k <= c; k ++)
                    ans.jz[i][j] = (ans.jz[i][j] + jz[i][k] * rhs.jz[k][j] % mod) % mod;
        return ans;
    }
}A;
vector <int> G[M];
map <node, int> m;
int n, c, maxn[M], cnt;
LL ans;

void dfs (int Index, node x){
    if (Index == 27){
        m[x] = ++ cnt;
        return ;
    }
    if (! maxn[Index])
        dfs (Index + 1, x);
    else{
        for (int i = 0; i < maxn[Index]; i ++){
            x.v[Index] = i;
            dfs (Index + 1, x);
        }
    }
}
void Solve (int Index, node x){
    if (Index == 27){
        ans = (ans + A.jz[1][m[x]]) % mod;
        return ;
    }
    if (! maxn[Index])
        Solve (Index + 1, x);
    else{
        for (int i = 0; i < maxn[Index]; i ++){
            bool flag = 0;
            for (int j = 0; j < G[Index].size (); j ++){
                if (i % G[Index][j] == 0){
                    flag = 1;
                    break;
                }
            }
            if (flag){
                x.v[Index] = i;
                Solve (Index + 1, x);
            }
        }
    }
}
inline edge qkpow (edge x, LL y){
    edge ans;
    ans.r = ans.c = 123;
    for (register int i = 1; i <= ans.r; i ++)
        for (register int j = 1; j <= ans.c; j ++)
            if (i != j)
                ans.jz[i][j] = 0;
            else
                ans.jz[i][j] = 1;
    while (y > 0){
        if (y % 2 == 1)
            ans = ans * x;
        x = x * x;
        y /= 2;
    }
    return ans;
}
int main (){
    scanf ("%d %d", &n, &c);
    if (! n){
        printf ("1\n");
        return 0;
    }
    if (! c){
        printf ("0\n");
        return 0;
    }
    for (int i = 1; i <= c; i ++){
        char a;
        int b;
        scanf ("\n%c %d", &a, &b);
        if (! maxn[a - 'A' + 1])
            maxn[a - 'A' + 1] = b;
        else
            maxn[a - 'A' + 1] *= b;
        G[a - 'A' + 1].push_back (b);
    }
    dfs (1, prepare);
    for (map <node, int> :: iterator i = m.begin (); i != m.end (); i ++){
        int Second = i -> second;
        node First = i -> first;
        for (int j = 1; j <= 26; j ++){
            if (maxn[j]){
                node tmp = First;
                tmp.v[j] = (tmp.v[j] + 1) % maxn[j];
                A.jz[Second][m[tmp]] ++;
            }
        }
    }
    A.r = A.c = 123;
    A = qkpow (A, n - 1);
    Solve (1, prepare);
    printf ("%lld\n", ans);
    return 0;
}

#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <cstring>
#define MOD 12345
using namespace std;
#define pb(a) push_back(a)
#define fi first
#define se second
typedef pair<int,int> pii;
typedef pair<char,pii> data;
vector<data> rules,tmp;
set<char> EQ,BAN;
long long n;
int c,M;
typedef map< vector<data> , int > STATE;
typedef map< int , vector<data> > REV;
STATE states;
REV rev;
void gen_all_states(int p){
  if(p==rules.size()){states.insert(make_pair(tmp,0)); return;}
  tmp.pb(rules[p]);
  for(int i=0;i<tmp.back().se.fi;++i){
   tmp.back().se.se=i;
   gen_all_states(p+1);
                                     }
  tmp.pop_back();
}
int GO(vector<data>& w , char C){
  for(int i=0;i<w.size();++i)
   if(w[i].fi==C){++w[i].se.se; if(w[i].se.se>=w[i].se.fi)w[i].se.se=0;}
  int ret=states[w];
  for(int i=0;i<w.size();++i)
   if(w[i].fi==C){--w[i].se.se; if(w[i].se.se<0)w[i].se.se=w[i].se.fi-1;}
  return ret;
}
// MATRIX SOLUTION
typedef long long ll;
struct MATR{
  ll D[200][200];
  MATR(){memset(D,0,sizeof D);}
  void ONE(){for(int i=0;i<M;++i)D[i][i]=1;}
  MATR operator*(MATR& w){
   MATR ret;
   for(int i=0;i<M;++i)
    for(int j=0;j<M;++j)
     for(int k=0;k<M;++k)
      ret.D[i][j]+=D[i][k]*w.D[k][j];
   for(int i=0;i<M;++i)
    for(int j=0;j<M;++j)ret.D[i][j]%=MOD;
   return ret;
                         }
};
MATR B;
MATR POW(ll step){
  MATR ret; ret.ONE();
  for(;step;step>>=1,B=B*B)
   if(step&1)ret=B*ret;
  return ret;
}
// FINAL
int CU[300],ust;
bool OK(vector<data> w){
  ++ust;
  for(int i=0;i<w.size();++i)
   if(!w[i].se.se)CU[w[i].fi]=ust;
  for(int i=0;i<w.size();++i)
   if(CU[w[i].fi]!=ust)return false;
  return true;
}
int main(){
  cin>>n>>c;
  if(n==0){cout<<1<<'\n'; return 0;}
  for(char i='A';i<='Z';++i)BAN.insert(i);
  for(int i=0;i<c;++i){
   char D; int br;
   cin>>D>>br;
   BAN.erase(D);
   if(br==1)EQ.insert(D);
   else tmp.pb(data(D,pii(br,0)));
                      }
  for(int i=0;i<tmp.size();++i)
   if(EQ.count(tmp[i].fi))continue;
   else rules.pb(tmp[i]);
  tmp.clear();
  // when rules are empty?
  if(rules.empty())
   rules.pb(data('?',pii(1,0)));
  gen_all_states(0);
  for(STATE::iterator it=states.begin();it!=states.end();++it){
   it->se=M++;
   rev[it->se]=it->fi;
                                                              }
  for(STATE::iterator it=states.begin();it!=states.end();++it){
   vector<data> USE=it->fi;
   for(char C='A';C!='Z';++C)
    if(!BAN.count(C))++B.D[it->se][GO(USE,C)];
                                                              }
  B=POW(n);
  int START=states[rules];
  ll ans=0;
  for(int i=0;i<M;++i)
   if(OK(rev[i]))ans+=B.D[START][i];
  ans%=MOD;
  cout<<ans<<'\n';
  //system("pause");
  return 0;
}

#include <vector>
#include <map>
#include <unordered_map>
#include <set>
#include <unordered_set>
#include <queue>
#include <stack>
#include <algorithm>
#include <iostream>
#include <string>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <cmath>
#include <climits>
#include <cctype>
#include <iomanip>
#include <bitset>
#include <list>
#include <deque>
#include <utility>
#include <functional>
#include <cassert>
#include <complex>

using namespace std;

#define all(a)              (a).begin(), (a).end()
#define ms(a,b)             memset(a, b, sizeof(a))
#define mp                  make_pair
#define pb                  push_back
#define fore(it,a)          for (auto it = (a).begin(), it##_ = (a).end(); it != it##_; ++it)
#define f0r(i, a)           for (int i = 0, i##_ = (a); i < i##_; ++i)
#define debug(args...)      do {cerr << #args << ": "; dbg,args; cerr << endl;} while(0)
#define read(type, args...) type args; rdr,args;
#define fi                  first
#define se                  second
#define bit_no              __builtin_popcount
#define left(a)             (2*(a))
#define right(a)            (2*(a)+1)
#define mid(left, right)    (((left)+(right))/2+1)
#define PI                  acos(-1)

typedef long long               ll;
typedef long double             ld;
typedef unsigned long long      ull;
typedef vector<int>             vi;
typedef vector<vi>              vvi;
typedef pair<int, int>          ii;
typedef tuple<int, int, int>    iii;
typedef vector<ii>              vii;
typedef vector<iii>             viii;

template<typename T>
using min_pq = priority_queue<T, vector<T>, greater<T>>;

const int inf = 2e8+5;
const ll l_inf = 9e18+5;
const int mod_v = 12345;
const int max_n = 1e5+5;

template<typename T>
T gcd(T a, T b)
{
    while (b) {
        T temp = a % b;
        a = b;
        b = temp;
    }
    return a;
}

template<typename T>
tuple<T, T, T> egcd(T a, T b)
{
    T x1 = 1, x2 = 0, y1 = 0, y2 = 1;
    while (b) {
        T q = a / b, r = a % b;
        T new_x = x1 - q*x2, new_y = y1 - q*y2;
        x1 = x2, y1 = y2, x2 = new_x, y2 = new_y;
        a = b, b = r;
    }
    return make_tuple(a, x1, y1);
}

inline ll lcm(ll a, ll b)
{
    return a*b/gcd(a, b);
}

template<typename T>
inline T mod(T a, T b = mod_v)
{
    return (a % b + b) % b;
}

template<typename T>
inline T mod_inv(T a, T b = mod_v)
{
    return mod(get<1>(egcd(a, b)), b);
}

template<typename T>
inline T sum(T a, T b, T m = mod_v)
{
    return mod(mod(a, m) + mod(b, m), m);
}

template<typename T>
inline T difference(T a, T b, T m = mod_v)
{
    return mod(mod(a, m) - mod(b, m), m);
}

inline ll product(ll a, ll b, ll m = mod_v)
{
    return mod(mod(a, m) *  mod(b, m), m);
}

inline ll quotient(ll a, ll b, ll m = mod_v)
{
    return mod(mod(a, m) * mod_inv(b, m), m);
}

template<typename T,typename T2>
ostream& operator<< (ostream &s, const pair<T,T2> &p) {return s << p.fi << ' ' << p.se << ' ';}

template<typename T,typename T2>
istream& operator>> (istream &s, pair<T,T2> &p) {return s >> p.fi >> p.se;}

template<typename T>
ostream& operator<< (ostream &s, const vector<T> &v)  {for (auto it: v) s << it << ' '; return s;}

template<typename T>
istream& operator>> (istream &s, vector<T> &v) {fore (it, v) s >> *it; return s;}

template<typename T>
void read_range(T beg, T end)
{
    while (beg != end)
        cin >> *beg++;
}

template<typename T>
void print_range(T beg, T end)
{
    while (beg != end)
        cout << *beg++ << ' ';
}

struct reader
{
    template<typename T>
    reader& operator, (T &v)
    {
        cin >> v;
        return *this;
    }
} rdr;

struct debugger
{
    template<typename T>
    debugger& operator, (const T &v)
    {
        cerr << v << ", ";
        return *this;
    }
} dbg;

/***************************************************************
----------------------------------------------------------------
----------------------------------------------------------------
***************************************************************/

int ar[123][123];
int res[123][123];
int temp[123][123];
int mult[26];
unordered_map<string, int> v2i;
unordered_map<int, string> i2v;
int s_no;

void prod(int a[][123], const int b[][123])
{
    f0r (i, s_no)
        f0r (j, s_no) {
            temp[i][j] = 0;
            f0r (k, s_no)
                temp[i][j] = (temp[i][j] + a[i][k] * b[k][j]) % mod_v;
        }
    memcpy(a, temp, sizeof(temp));
}

void power(ll p)
{
    f0r (i, s_no)
        res[i][i] = 1;
    while (p) {
        if (p & 1)
            prod(res, ar);
        prod(ar, ar);
        p >>= 1;
    }
}

void init_hash(int i, string p)
{
    if (i == 26) {
        /*debug(s_no);
        for (int k: p)
            cout << k << ' ';
        cout << endl;*/
        v2i[p] = s_no;
        i2v[s_no++] = p;
        return;
    }
    if (mult[i] == 0) {
        init_hash(i + 1, p);
        return;
    }

    //debug(i, mult[i]);
    f0r (j, mult[i]) {
        p.pb(j);
       // debug(j);
        init_hash(i + 1, p);
        p.pop_back();
    }
}

void init_ar()
{
    f0r (i, s_no) {
        string new_s(i2v[i]);
        int cnt = 0;
        f0r (j, 26)
            if (mult[j]) {
                //debug((int)new_s[cnt]);
                new_s[cnt] = (new_s[cnt] + 1) % mult[j];
                //debug((int)new_s[cnt]);
                int new_s_no = v2i[new_s];
                //debug(i, j, new_s_no);
                ar[i][new_s_no]++;
                new_s[cnt]--;
                if (new_s[cnt] == -1)
                    new_s[cnt] = mult[j] - 1;
                cnt++;
            }
    }
}

int main()
{
    ios_base::sync_with_stdio(false);

    read(ll, n);
    read(int, c);

    f0r (i, c) {
        read(char, ch);
        read(int, m);
        if (mult[ch - 'A'] == 0)
            mult[ch - 'A'] = m;
        else
            mult[ch - 'A'] = lcm(mult[ch - 'A'], m);
    }

    string blank;
    init_hash(0, blank);
    init_ar();

   /*
    debug(s_no);
    f0r (i, s_no) {
        print_range(ar[i], ar[i] + s_no);
        cout << '\n';
    }
    */

    power(n);

    cout << res[0][0];

    return 0;
}

#define _CRT_SECURE_NO_DEPRECATE
#pragma comment(linker, "/STACK:64000000")

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <cctype>
#include <cmath>
#include <algorithm>
#include <utility>
#include <memory.h>
#include <cstring>

#include <set>
#include <map>
#include <vector>
#include <string>
#include <queue>

#include <iostream>
#include <sstream>

using namespace std;

typedef long long int64;

#define forn(i, n) for(int i = 0; i < (int)(n); i++)
#define ford(i, n) for(int i = (int)(n) - 1; i >= 0; i--)
#define pb push_back
#define mp make_pair
#define all(a) a.begin(), a.end()

const int INF = (int)1E9;
const int64 INF64 = (int64)1E18;
const long double EPS = 1E-8;
const long double PI = 3.1415926535897932384626433832795;

const int MAXN = 150;
const int MOD = 12345;

void mult(int a[MAXN][MAXN], int b[MAXN][MAXN]) {
    int res[MAXN][MAXN];
    memset(res, 0, sizeof res);

    forn(i, MAXN)
        forn(j, MAXN)
            forn(k, MAXN)
                res[i][j] = (res[i][j] + a[i][k] * b[k][j]) % MOD;

    memcpy(a, res, sizeof res);
}

void bpow(int a[MAXN][MAXN], int64 b) {
    int res[MAXN][MAXN];
    memset(res, 0, sizeof res);
    forn(i, MAXN) res[i][i] = 1;

    while (b > 0)
        if (b % 2 == 0) {
            mult(a, a);
            b /= 2;
        } else {
            mult(res, a);
            b--;
        }

    memcpy(a, res, sizeof res);
}

int n, len[1200], mul[1200], m[MAXN][MAXN];
vector<int> g[30];

void IntToArray(int v, int * a) {
    ford(i, n) {
        a[i] = v / mul[i];
        v %= mul[i];
    }
}

int ArrayToInt(int * a) {
    int ans = 0;
    forn(i, n)
        ans += a[i] * mul[i];
    return ans;
}

int main(){
#ifndef ONLINE_JUDGE
    freopen("input.txt", "rt", stdin);
    freopen("output.txt", "wt", stdout);
#endif

    int64 p;
    cin >> p >> n;
    forn(i, n) {
        char c;
        scanf(" %c%d", &c, &len[i]);
        g[c - 'A'].pb(i);

        if (i == 0)
            mul[i] = 1;
        else
            mul[i] = mul[i - 1] * len[i - 1];
    }

    mul[n] = mul[n - 1] * len[n - 1];
    forn(v, 26) {
        if (g[v].empty()) continue;

        forn(mask, mul[n]) {
            int a[1200];
            IntToArray(mask, a);

            forn(i, g[v].size()) {
                int pos = g[v][i];
                a[pos] = (a[pos] + 1) % len[pos];
            }

            m[mask][ArrayToInt(a)]++;
        }
    }

    bpow(m, p);

    int ans = 0;
    forn(mask, mul[n]) {
        int a[1200];
        IntToArray(mask, a);

        bool ok = true;
        forn(v, 26) {
            bool ok1 = g[v].empty();
            forn(i, g[v].size()) {
                int pos = g[v][i];
                if (a[pos] == 0) ok1 = true;
            }

            ok &= ok1;
        }

        if (ok) ans = (ans + m[0][mask]) % MOD;
    }

    cout << ans << endl;

    return 0;
}

#include<stdio.h>
#include<iostream>
#include<algorithm>
#include<string.h>
#include<map>
#include<cmath>
#include<vector>
#include<string>
using namespace std;
const int N=200;
const int mod=12345;
typedef long long LL;
#define pb push_back

int n;

void mul(int aa[N][N],int bb[N][N]){
    int cc[N][N];
    memset(cc,0,sizeof(cc));
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            for(int k=0;k<n;k++){
                cc[i][j]+=aa[i][k]*bb[k][j]%mod;cc[i][j]%=mod;
            }
        }
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            aa[i][j]=cc[i][j];
        }
    }
}

void _powm(int aa[N][N],int b){
    int cc[N][N];
    memset(cc,0,sizeof(cc));
    for(int i=0;i<n;i++)cc[i][i]=1;
    while(b){
        if(b&1){
            mul(cc,aa);
        }
        mul(aa,aa);b/=2;
    }
    for(int i=0;i<n;i++){
        for(int j=0;j<n;j++){
            aa[i][j]=cc[i][j];
        }
    }
}

int sta[30],top;
int tt[N][N],aa[N][N],bb[N][N];
vector<int> vv[30];
vector<int> ww[30];
int fun(int sta2,int xx){
    //printf("fun\n");
    int sta1=0;
    //printf("%d %d\n",top,ww[0].size());
    for(int i=0;i<top;i++){
        for(int j=0;j<ww[i].size()-1;j++){
            //printf("%dvv\n",vv[i][j]);
            int x=sta2%ww[i][j+1]/ww[i][j];
            //printf("%dx\n",x);
            if(i!=xx){
                sta1+=x*ww[i][j];
            }
            else {
                x++;x%=vv[sta[i]][j];
                sta1+=x*ww[i][j];
            }
        }
    }
    //printf("%dfun\n",sta1);
    return sta1;
}
int check(int sta){
    int cnt=0;
    for(int i=0;i<top;i++){
        for(int j=0;j<ww[i].size()-1;j++){
            int x=sta%ww[i][j+1]/ww[i][j];
            if(x==0){
                cnt++;break;
            }
        }
    }
    return cnt==top;
}

int main(){
    #ifdef DouBi
    freopen("in.cpp","r",stdin);
    #endif // DouBi
    int a,b;
    while(scanf("%d%d",&a,&b)!=EOF){
        for(int i=0;i<26;i++)vv[i].clear();
        for(int i=0;i<b;i++){
            char ss[2];int v;scanf("%s%d",ss,&v);
            vv[ss[0]-'A'].pb(v);
        }
        for(int i=0;i<26;i++){
            sort(vv[i].begin(),vv[i].end());
        }

        top=0;
        int cnt=0;
        for(int i=0;i<26;i++){
            if(vv[i].size()){
                if(vv[i][0]>1)sta[top++]=i;
                else if(vv[i][0]==1){
                    cnt++;
                }
            }
        }

        int sz=1;
        for(int i=0;i<top;i++){
            ww[i].clear();
            for(int j=0;j<vv[sta[i]].size();j++){
                ww[i].pb(sz);
                sz*=vv[sta[i]][j];
            }
            ww[i].pb(sz);
        }
        //for(int i=0;i<top;i++)printf("%d %d\n",sta[i],ww[i].size());
        //printf("%dsz %dtop %dcb\n",sz,top,cnt);
//        for(int i=0;i<3;i++){
//            printf("%dsz\n",vv[i].size());
//        }
        n=sz;
        memset(tt,0,sizeof(tt));
        for(int i=0;i<sz;i++){
            tt[i][i]=cnt;
            for(int j=0;j<top;j++){
                int x=fun(i,j);
                //printf("%d %dj %dx\n",i,j,x);
                tt[i][x]++;
            }
        }
//        for(int i=0;i<sz;i++){
//            for(int j=0;j<sz;j++){
//                printf("%d ",tt[i][j]);
//            }printf("\n");
//        }
        _powm(tt,a);
//        for(int i=0;i<sz;i++){
//            for(int j=0;j<sz;j++){
//                printf("%d ",tt[i][j]);
//            }printf("\n");
//        }
        int ans=0;
        for(int i=0;i<sz;i++){
            if(check(i)){
                ans+=tt[0][i];ans%=mod;
            }
        }
        printf("%d\n",ans);
    }
    return 0;
}

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author Ankur Dua
 */

#include <iostream>
#include <fstream>

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
ll mod=1000000007;
ll *fact, *ifact;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

ll modExp(ll base, ll exp, ll mod=::mod){
    ll ans=1;
    while(exp) {
        if (exp & 1) {
            (ans *= base) %= mod;
        }
        (base *= base) %= mod;
        exp>>=1;
    }
    return ans;
}
ll modInv(ll x, ll mod=::mod){
    return modExp(x,mod-2,mod);
}
void modFact(ll n, ll mod=::mod){
    ifact=new ll[n+1];
    fact=new ll[n+1];
    fact[0]=fact[1]=1;
    for(int i=2;i<=n;i++){
        fact[i]=(i*fact[i-1])%mod;
    }
    ifact[n]=modInv(fact[n], mod);
    for(int i=n-1;i>=0;i--){
        ifact[i]=((i+1)*ifact[i+1])%mod;
    }
}
ll ncr(ll n, ll r, ll mod=::mod){
    if(n<r || r<0)
        return 0;
    ll ans=fact[n];
    ans*=ifact[r];
    ans%=mod;
    ans*=ifact[n-r];
    ans%=mod;
    return ans;
}
ll npr(ll n, ll r, ll mod=::mod){
    if(n<r || r<0)
        return 0;
    ll ans=fact[n];
    ans*=ifact[n-r];
    return ans%mod;
}

template <typename T>
void coordinateCompress(vector<T> &v, T start = 1){
    vector<T> cpy = v;
    sort(cpy.begin(), cpy.end());
    map<T,T> mp;
    for(T x:cpy){
        mp[x]=start++;
    }
    for(T &x:v){
        x=mp[x];
    }
}
template<typename T1, typename T2>
istream& operator >>(istream& cin, pair<T1, T2> &p){
	cin>>p.first>>p.second;
	return cin;
}
using namespace std;

vector<vector<ll>> operator *(vector<vector<ll>> &a, vector<vector<ll>> &b){
	int n=a.size();
	vector<vector<ll>> ans(n, vector<ll>(n));
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			ll &val=ans[i][j];
			for(int k=0;k<n;k++){
				val+=a[i][k]*b[k][j];
			}
			val%=12345;
		}
	}
	return ans;
}
class DCrimeManagement {
public:

	void solve(std::istream& cin, std::ostream& cout) {
		ll n, c;
		cin>>n>>c;
		if(n==0){
			cout<<1<<endl;
			return;
		}
		if(c==0){
			cout<<0<<endl;
			return;
		}
		vector<vector<int>> v(26);
		for(int i=0;i<c;i++){
			char c;
			int x;
			cin>>c>>x;
			v[c-'A'].push_back(x);
		}
		v.resize(remove_if(v.begin(), v.end(), [](vector<int> x){return x.empty();})-v.begin());
		vector<int> product(v.size());
		for(int i=0;i<v.size();i++){
			product[i]=1;
			for(int x:v[i])
				product[i]=(product[i]*x)/__gcd(product[i], x);
		}
		int m=product.size();
		vector<vector<int>> ways;
		ways.push_back(vector<int>());
		for(int x:product){
			vector<vector<int>> ways2;
			for(int i=0;i<x;i++){
				for(auto way:ways){
					way.push_back(i);
					ways2.push_back(way);
				}
			}
			swap(ways, ways2);
		}
		int sz=ways.size();

		vector<vector<ll>> mat(sz, vector<ll>(sz));
		for(int i=0;i<sz;i++){
			for(int j=0;j<m;j++){
				vector<int> way=ways[i];
				way[j]--;
				if(way[j]<0)
					way[j]+=product[j];

				mat[i][i]++;
			}
		}
		vector<vector<ll>> ans(sz, vector<ll>(sz));
		for(int i=0;i<sz;i++)ans[i][i]=1;
		while(n){
			if(n&1){
				ans=ans*mat;
			}
			n>>=1;
			mat=mat*mat;
		}
		ll sum=0;
		for(int i=0;i<sz;i++){
			bool valid=true;
			vector<int> way=ways[i];
			for(int j=0;j<m;j++){
				bool flag=false;
				for(int x:v[j])
					if(way[j]%x==0)
						flag=true;
				valid=valid&&flag;
			}
			if(valid)
				sum+=ans[i][0];
		}
		cout<<(sum%12345)<<endl;
	}
};

int main() {
	DCrimeManagement solver;
	std::ios::sync_with_stdio(false);
	std::cin.tie(NULL);
	std::cout.tie(NULL);
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
	return 0;
}

#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
#include <map>
#include <cstdio>
#include <memory.h>

using namespace std;

const long long MOD = 12345;

long long GCD(long long a, long long b)
{
	while(a > 0)
	{
		if(a < b)
			swap(a, b);
		a %= b;
	}
	return b;
}

long long LCM(long long a, long long b)
{
	if(a * b == 0)
		return max(a, b);
	return a * b / GCD(a, b);
}

vector <long long> arr, now;
map <vector <long long>, long long> b;

void Fill(long long n)
{
	if(n == arr.size())
	{
		long long t = b.size();
		b[now] = t;
		return;
	}
	for(long long i = 0; i < arr[n]; i++)
	{
		now[n] = i;
		Fill(n + 1);
	}
}

struct M
{
	long long arr[130][130];
	M()
	{
		memset(arr, 0, sizeof(arr));
	}
	M& operator =(const M &a)
	{
		memcpy(arr, a.arr, sizeof(arr));
		return *this;
	}
	M operator * (const M &a)
	{
		M ans;
		for(long long i = 0; i < 130; i++)
			for(long long j = 0; j < 130; j++)
				for(long long k = 0; k < 130; k++)
				{
					ans.arr[i][j] += arr[i][k] * a.arr[k][j];
					ans.arr[i][j] %= MOD;
				}
		return ans;
	}
};

M E()
{
	M ans;
	for(long long i = 0; i < 130; i++)
		ans.arr[i][i] = 1;
	return ans;
}

M gr, a;

vector <vector <long long> > dd, d;
vector <bool> f;

int main()
{
#ifndef ONLINE_JUDGE
	freopen("input.txt", "r", stdin);
#endif
	long long n;
	long long m;
	cin >> n >> m;
	vector <long long> tmp(26, 0);
	dd.resize(26);
	for(long long i = 0; i < m; i++)
	{
		char c;
		long long x;
		cin >> c >> x;
		tmp[c - 'A'] = LCM(tmp[c - 'A'], x);
		dd[c - 'A'].push_back(x);
	}

	for(long long i = 0; i < m; i++)
		if(tmp[i] != 0)
		{
			arr.push_back(tmp[i]);
			d.push_back(dd[i]);
		}
	now.resize(arr.size());
	Fill(0);
	if(b.size() > 130)
		throw(0);
	f.assign(b.size(), true);
	for(map <vector <long long>, long long>::iterator it = b.begin(); it != b.end(); it++)
	{
		vector <long long> now = it->first;
		for(long long i = 0; i < now.size(); i++)
		{
			bool ok = false;
			for(long long j = 0; j < d[i].size(); j++)
				if(now[i] % d[i][j] == 0)
					ok = true;
			if(!ok)
				f[it->second] = false;
		}
		for(long long i = 0; i < now.size(); i++)
		{
			vector <long long> tmp = now;
			tmp[i]++;
			tmp[i] %= arr[i];
			if(!b.count(tmp))
				throw(0);
			gr.arr[it->second][b[tmp]]++;
			gr.arr[it->second][b[tmp]] %= MOD;
		}
	}
	a = gr;
	gr = E();
	while(n > 0)
	{
		if(n % 2 == 1)
		{
			gr = gr * a;
			n--;
		}
		else
		{
			a = a * a;
			n /= 2;
		}
	}
	long long ans = 0;
	for(long long i = 0; i < b.size(); i++)
		if(f[i])
		{
			ans += gr.arr[0][i];
			ans %= MOD;
		}
	cout << ans << endl;
	return 0;
}

#include <cstdio>
#include <cstring>
#include <climits>
#include <cstdlib>
#include <algorithm>
#include <vector>
#include <iostream>
#include <set>
#include <map>
using namespace std;
const int MOD = 12345;
const int STD_SIZE = 130;
int msize;
struct Matrix {
    int mat[STD_SIZE][STD_SIZE];
    Matrix () {memset(mat, 0, sizeof mat);}
    inline Matrix operator * (const Matrix & b) {
        Matrix ret;
        for(int i = 0; i<msize; i++)
            for(int j = 0; j<msize; j++)
                for(int k = 0; k<msize; k++)
                    ret.mat[i][j] = (ret.mat[i][j]+mat[i][k]*b.mat[k][j])%MOD;
        return ret;
    }
};
map<char, vector<int> > mp;
int lvl[30], prd[30];
bool vis[STD_SIZE], nvalid[STD_SIZE];
int main () {
    int N, C;
    scanf("%d%d", &N, &C);
    for(int i = 1; i<=C; i++) {
        char buf[10]; int val;
        scanf("%s%d", buf, &val);
        mp[buf[0]].push_back(val);
    }
    for(char chr = 'A'; chr <= 'Z'; chr++) {
        vector<int>&tmp = mp[chr];
        sort(tmp.begin(), tmp.end());
        tmp.erase(unique(tmp.begin(), tmp.end()), tmp.end());
        lvl[chr-'A'+1] = 1;
        for(int i = 0; i<(int)tmp.size(); i++)
            lvl[chr-'A'+1] = lvl[chr-'A'+1]*tmp[i];
    }
    prd[0] = lvl[0] = 1;
    for(int i = 1; i<=26; i++)
        prd[i] = prd[i-1]*lvl[i];
    msize = prd[26];
    Matrix unit, mfac;
    for(int i = 0; i<msize; i++) unit.mat[i][i] = 1;
    for(int cur = 0; cur<msize; cur++) {
        for(int nxt = 0; nxt<26; nxt++) {
            if(mp['A'+nxt].size() == 0) continue ;
            int cbit = cur/prd[nxt]%lvl[nxt+1];
            int nbit = (cbit+1)%lvl[nxt+1];
            int delta = (nbit-cbit)*prd[nxt];
            mfac.mat[cur][cur+delta] ++;
        }
    }
    while(N) {
        if(N&1) unit = unit*mfac;
        mfac = mfac*mfac;
        N >>= 1;
    }
    int ans = 0;
    for(int chr = 0; chr<26; chr++) {
        vector<int>&tmp = mp['A'+chr];
        if(tmp.size() == 0) continue ;
        memset(vis, 0, sizeof vis);
        for(int i = 0; i<(int)tmp.size(); i++)
            for(int j = 0; j<msize; j+=tmp[i])
                vis[j] = true;
        for(int i = 0; i<msize; i++)
            if(!vis[i]) nvalid[i] = true;
    }
    for(int i = 0; i<msize; i++) {
        if(nvalid[i]) continue ;
        ans = (ans+unit.mat[0][i]);
    }
    cout << ans << '\n';
}

#include<iostream>
#include<vector>
#include<string>
#include<cmath>
#include<ctime>
#include<algorithm>
#include<queue>
#include<stack>
#include<cstdlib>
#include<utility>
#include<map>
#include<set>
#include<fstream>
#include<iomanip>
#include<cstdio>
#define D double
#define PB push_back
#define F first
#define S second
#define MP make_pair
using namespace std;
typedef long long ll;
typedef pair<int,int> PII;
typedef vector< vector<int> > VV;
const int MOD = 12345;

vector<int> v[40],help;
vector< vector<int> > A;
vector<int> kmm;
int M = 1,esh[30];

int asl_code(vector<int> &a){
	int ans = 0;
	for(int i = a.size()-1;i >= 0;i--){
		ans *= kmm[i];
		ans += a[i];
	}
	return ans;
}
vector<int> code_asl(int x){
	vector<int> ans;
	for(int i = 0; i < (int)kmm.size(); i++){
		ans.PB(x % kmm[i]);
		x /= kmm[i];
	}
	return ans;
}

VV MUL(VV x, VV y){
	VV ans(M);
	for (int i = 0; i < M; i++)
		ans[i].resize(M);
	for(int i = 0;i < M; i++)
		for(int j = 0;j < M; j++)
			for(int k = 0;k < M;k++)
				ans[i][j] = (ans[i][j] + x[i][k]*y[k][j]) % MOD;
	return ans;
}

VV PW(long long w){ // w != 0
	if(w == 1)
		return A;
	VV tmp = PW(w/2);
	if(w % 2 == 0)
		return MUL( tmp, tmp);
	return MUL(MUL(tmp,tmp),A);
}

int main(){
	ios::sync_with_stdio(false);
	long long n,m;cin >> n >> m;
	for(int i = 0;i < m;i++){
		char c;int x;cin >> c >> x;
		v[c-'A'].PB(x);
	}
	if(n == 0){
		cout << 1 <<endl;
		return 0;
	}
	for(int  i = 0;i < 30;i++){
		sort(v[i].begin(),v[i].end());
		unique(v[i].begin(),v[i].end());
	}
	for(int i = 0;i < 26;i++){
		if(v[i].size() == 0)
			continue;
		esh[kmm.size()] = i;
		int q = 1;
		for(int j = 0;j <(int)v[i].size();j++)
			q *= v[i][j];
		kmm.PB(q);
		M *= q;
	}
	A.resize(M);
	for(int i = 0;i < M; i++)
		A[i].resize(M);
	for(int i = 0;i < M;i++){
		vector<int> q = code_asl(i);
		for(int j = 0;j < (int)q.size();j++){
			q[j] = (q[j]-1+kmm[j])%kmm[j];
			int carr = asl_code(q);
			A[carr][i] = 1;
			q[j] = (q[j]+1)%kmm[j];
		}
	}
	VV qq = PW(n);
	long long res = 0;
	for(int i = 0;i < M;i++){
		vector<int> r = code_asl(i);
		bool ok = true;
		for(int j = 0;j < (int)r.size(); j++){
			bool help = false;
			for(int k = 0;k < (int)v[ esh[j] ].size();k++)
				if(r[j] % v[esh[j]][k] == 0)
					help = true;
			if(!help){
				ok = false;
				break;
			}
		}
		if(!ok)
			continue;
		res = (res+qq[i][0])%MOD;
	}
	cout << res <<endl;
	return 0;
}

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author Ankur Dua
 */

#include <iostream>
#include <fstream>

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
ll mod=1000000007;
ll *fact, *ifact;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

template<typename T1, typename T2>
istream& operator >>(istream& cin, pair<T1, T2> &p){
	cin>>p.first>>p.second;
	return cin;
}
using namespace std;

vector<vector<ll>> operator *(vector<vector<ll>> &a, vector<vector<ll>> &b){
	int n=a.size();
	vector<vector<ll>> ans(n, vector<ll>(n));
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			ll &val=ans[i][j];
			for(int k=0;k<n;k++){
				val+=a[i][k]*b[k][j];
			}
			val%=12345;
		}
	}
	return ans;
}
class DCrimeManagement {
public:

	void solve(std::istream& cin, std::ostream& cout) {
		ll n, c;
		cin>>n>>c;
		if(n==0){
			cout<<1<<endl;
			return;
		}
		if(c==0){
			cout<<0<<endl;
			return;
		}
		vector<vector<int>> v(26);
		for(int i=0;i<c;i++){
			char c;
			int x;
			cin>>c>>x;
			v[c-'A'].push_back(x);
		}
		v.resize(remove_if(v.begin(), v.end(), [](vector<int> x){return x.empty();})-v.begin());
		vector<int> product(v.size());
		for(int i=0;i<v.size();i++){
			product[i]=1;
			for(int x:v[i])
				product[i]=(product[i]*x)/__gcd(product[i], x);
		}
		int m=product.size();
		vector<vector<int>> ways;
		ways.push_back(vector<int>());
		for(int x:product){
			vector<vector<int>> ways2;
			for(int i=0;i<x;i++){
				for(auto way:ways){
					way.push_back(i);
					ways2.push_back(way);
				}
			}
			swap(ways, ways2);
		}

		int sz=ways.size();
		map<vector<int>, int> mp;
		for(int i=0;i<ways.size();i++)
			mp[ways[i]]=i;
		vector<vector<ll>> mat(sz, vector<ll>(sz));
		for(int i=0;i<sz;i++){
			for(int j=0;j<m;j++){
				vector<int> way=ways[i];
				way[j]--;
				if(way[j]<0)
					way[j]+=product[j];
				int nextWay=mp[way];
				mat[i][nextWay]++;
			}
		}
			for(auto i:mat)
			for(auto j:i)
					cout << j << " ";
			cout <<endl;
		vector<vector<ll>> ans(sz, vector<ll>(sz));
		for(int i=0;i<sz;i++)ans[i][i]=1;
		while(n){
			if(n&1){
				ans=ans*mat;
			}
			n>>=1;
			mat=mat*mat;
		}

		ll sum=0;
		for(int i=0;i<sz;i++){
			bool valid=true;
			vector<int> way=ways[i];
			for(int j=0;j<m;j++){
				bool flag=false;
				for(int x:v[j])
					if(way[j]%x==0)
						flag=true;
				valid=valid&&flag;
			}
			if(valid)
				sum+=ans[i][sz-1];
		}
		cout<<(sum%12345)<<endl;
	}
};

int main() {
	DCrimeManagement solver;
	std::ios::sync_with_stdio(false);
	std::cin.tie(NULL);
	std::cout.tie(NULL);
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
	return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <set>
#include <algorithm>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <queue>

#define LL long long
#define mp(x, y) make_pair(x, y)
#define pb(x) push_back(x)
#define size(S) S.size()
#define PII pair<int, int>
#define PID pair<int, double>

using namespace std;

const int mo = 12345;
LL n;
int c, b, d[26][1010], p[26], cnt[26], all, gen[130], ova, tmp[26];
char a;
bool app[26];
struct matrix{
	int n, m, data[130][130];
} res, shift, ret, T;

matrix operator*(matrix a, matrix b){
	memset(T.data, 0, sizeof(T.data));
	T.n = a.n; T.m = b.m;
	for (int i = 0; i < a.n; i++)
		for (int j = 0; j < a.m; j++)
			for (int k = 0; k < b.m; k++)
				T.data[i][k] = (T.data[i][k] + a.data[i][j] * b.data[j][k]) % mo;
	return T;
}

void generate(int x, int v){
	if (x == 26) gen[ova++] = v;
	else for (int i = 0; i < p[x]; i++) generate(x + 1, v * p[x] + i);
}

void decode(int x){
	for (int i = 25; i >= 0; i--)
		tmp[i] = x % p[i], x /= p[i];
}

int code(){
	int ret = 0;
	for (int i = 0; i < 26; i++) ret = ret * p[i] + tmp[i];
	for (int i = 0; i < ova; i++) if (gen[i] == ret) return i;
	return -1;
}

void pow(LL x, matrix &s, matrix &ret){
	matrix tmp;
	for (ret = res, tmp = s; x; x >>= 1){
		if (x & 1) ret = ret * tmp;
		tmp = tmp * tmp;
	}
}

bool valid(){
	for (int i = 0; i < 26; i++){
		if (!app[i]) continue;
		bool find = false;
		for (int j = 0; j < cnt[i]; j++){
			if (tmp[i] % d[i][j] == 0){
				find = true;
				break;
			}
		}
		if (!find) return false;
	}
	return true;
}

int main(){
	for (int i = 0; i < 26; i++) p[i] = 1;
	for (cin >> n >> c; c; c--){
		cin >> a >> b;
		int t = a - 'A';
		d[t][cnt[t]++] = b; p[t] *= b; app[t] = true;
	}
	all = 1;
	for (int i = 0; i < 26; i++) all *= p[i];

	generate(0, 0);
	res.n = 1; res.m = all; shift.n = shift.m = all;
	for (int i = 0; i < all; i++){
		for (int j = 0; j < 26; j++){
			if (!app[j]) continue;
			decode(gen[i]);
			tmp[j] = (tmp[j] + 1) % p[j];
			int p = code();
			shift.data[i][p] = 1;
		}
	}
	res.data[0][0] = 1;

	int ans = 0;
	pow(n, shift, ret);
	for (int i = 0; i < ova; i++){
		decode(gen[i]);
		if (valid()) ans = (ans + ret.data[0][i]) % mo;
	}
	cout << ans << endl;
	return 0;
}

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int op=12345;
LL n;
int C,m,a[1100],b[1100],Q=0,ans=0;
char s[10],c[1100];
pair<char,int>e[1100];
int f[150][150],g[150][150],h[150],u[150],q[50][150];
void _pow()
{
	for(int i=0;i<b[m];++i)
		for(int j=0;j<b[m];++j)
		{
			g[i][j]=0;
			for(int k=0;k<b[m];++k)
				g[i][j]=(g[i][j]+f[i][k]*f[k][j])%op;
		}
	for(int i=0;i<b[m];++i)
		for(int j=0;j<b[m];++j)
			f[i][j]=g[i][j];
}
void Gans()
{
	memset(h,0,sizeof(h));
	h[0]=1;
	for(;n>0;n>>=1)
	{
		if ( n&1 )
		{
			for(int i=0;i<b[m];++i)
			{
				u[i]=0;
				for(int j=0;j<b[m];++j)
					u[i]=(u[i]+h[j]*f[j][i])%op;
			}
			for(int i=0;i<b[m];++i) h[i]=u[i];
		}
		_pow();
	}
}
void dfs(const int x,const int y)
{
	if ( x>m ) { ans+=h[y];return;}
	for(int i=0;i<a[x];++i)
		if ( q[x][i] )
		dfs(x+1,y+b[x-1]*i);
}
int main()
{
	scanf("%I64d%d",&n,&C);
	for(int i=1,x;i<=C;++i)
	{
		scanf("%s%d",s+1,&x);
		e[i]=make_pair(s[1],x);
	}
	sort(e+1,e+1+C);
	m=1;
	a[1]=e[1].second,c[1]=e[1].first;b[0]=1;
	for(int i=2;i<=C;++i)
	{
		if ( e[i].first!=e[i-1].first )
		{
			if ( a[m]!=1 )
				b[m]=b[m-1]*a[m],a[++m]=1;
			else ++Q;
			c[m]=e[i].first;
		}
		a[m]*=e[i].second;
	}
	if ( a[m]>1 ) b[m]=b[m-1]*a[m];else --m,++Q;
	for(int i=0;i<b[m];++i)
		for(int j=1;j<=m;++j)
			if ( i%b[j]>=b[j-1] ) f[i-b[j-1]][i]=1;
				else f[i+b[j]-b[j-1]][i]=1;
	for(int i=0;i<b[m];++i)
		f[i][i]=Q;
	Gans();
	for(int i=1,j=1;i<=C;++i)
	{
		while(c[j]<e[i].first && j<=m ) ++j;
		if ( j>m ) break;
		if ( c[j]!=e[i].first ) continue;
		for(int k=0;k<a[j];k+=e[i].second )
			q[j][k]=1;
	}
	dfs(1,0);
	cout<<ans%op<<endl;
	return 0;
}

#include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
#include <algorithm>
#include <cmath>
using namespace std;
#define rep(x, n) for (int x = 1; x <= n; ++x)
#define zrp(x, n) for (int x = n; x; --x)
#define FOR(x, l, r) for (int x = l; x <= r; ++x)
#define foredge(i, x) for (int i = start[x]; i; i = e[i].l)
#define max(a, b) ((a) > (b) ? (a) : (b))
#define min(a, b) ((a) < (b) ? (a) : (b))
#define abs(a) ((a) > 0 ? (a) : (-(a)))
typedef long long int64;
const int maxN = 130;
const int maxC = 1005;
const int Mod = 12345;

int mul(int x, int y)
{
    x *= y;
    if (x >= Mod) x %= Mod;
    return x;
}

void add(int &x, int y)
{
    x += y;
    if (x >= Mod) x -= Mod;
}

struct mat
{
    int n, m, g[maxN][maxN];
    mat operator*(const mat &o)
    {
        mat c;
        c.n = n; c.m = o.m;
        FOR(i, 0, n - 1) FOR(j, 0, o.m - 1)
        {
            c.g[i][j] = 0;
            FOR(k, 0, m - 1) add(c.g[i][j], mul(g[i][k], o.g[k][j]));
        }
        return c;
    }
}f, a;
int k, c[29], p[29], v[29][1005];
int64 n;

void make()
{
    int s1 = 0, s2;
    rep(i, 26) s1 = (s1 + c[i]) * p[i]; s1 /= k;
    rep(i, 26) if (v[i][0])
    {
        if (c[i] == p[i] - 1) c[i] = 0;
            else ++c[i];
        s2 = 0;
        rep(j, 26) s2 = (s2 + c[j]) * p[j]; s2 /= k;
        f.g[s1][s2]++;
        if (c[i] == 0) c[i] = p[i] - 1;
            else --c[i];
    }
}

void dfs(int x)
{
    if (x > 26)
        make();
    FOR(i, 0, p[x] - 1)
    {
        c[x] = i;
        dfs(x + 1);
    }
}

void init()
{
    char s[5]; int m, c;
    scanf("%I64d%d", &n, &c);
    rep(i, 26) p[i] = 1;
    rep(i, c)
    {
        scanf("%s%d", s, &m);
        p[s[0] - 64] *= m;
        v[s[0] - 64][++v[s[0] - 64][0]] = m;
    }
    zrp(i, 26) if (v[i][0])
    {
        k = p[i];
        break;
    }
    dfs(1);
    f.n = 1;
    rep(i, 26) f.n *= p[i];
    f.m = f.n;
}

bool check(int s)
{
    zrp(i, 26) c[i] = s % p[i], s /= p[i];
    rep(i, 26) if (v[i][0])
    {
        bool flag = 0;
        rep(j, v[i][0])
            if (c[i] % v[i][j] == 0)
            {
                flag = 1;
                break;
            }
        if (flag == 0) return 0;
    }
    return 1;
}

void work()
{
    a.n = 1; a.m = f.n;
    a.g[0][0] = 1;

    while (n)
    {
        if (n & 1) a = a * f;
        n >>= 1; f = f * f;
    }

    int ans = 0;
    FOR(i, 0, a.m - 1) if (check(i))
        add(ans, a.g[0][i]);
    printf("%d\n", ans);
}

int main()
{
    init();
    work();
    return 0;
}

#include<cstdio>
#include<cstring>
#include<vector>
#include<iostream>
#include<map>
using namespace std;
const int N = 505, oo = 12345;
int m, x, y, now, ans, a[N][N], b[N][N], c[N], e[N], s[N], res[N];
bool d[N][N], f[N];
char type[5];
vector<int> p(26);
map<vector<int>, int> h;
void mul1()
{
    memset(c, 0, sizeof(c));
    for (int i = 0; i < now; i++)
        for (int j = 0; j < now; j++)
            c[i] = (a[i][j] * res[j] + c[i]) % oo;
    memcpy(res, c, sizeof(res));
}
void mul()
{
    memset(b, 0, sizeof(b));
    for (int i = 0; i < now; i++)
        for (int j = 0; j < now; j++)
            for (int k = 0; k < now; k++)
                b[i][j]+=a[i][k] * a[k][j] + b[i][j];
    for (int i = 0; i < now; i++)
        for (int j = 0; j < now; j++)b[i][j]%=oo;
    memcpy(a, b, sizeof(a));
}
int dfs(vector<int> c)
{
    typeof(h.end()) it = h.find(c);
    if (it != h.end()) return it->second;
    int tmp = now++;
    h[c] = tmp;
    f[tmp] = 1;
    vector<int > b;
    for (int i = 0; i < 26; i++) if (e[i]) f[tmp] &= d[i][c[i]];
    for (int i = 0; i < 26; i++) if (e[i]) b = c, b[i] = (b[i] + 1) % s[i], a[dfs(b)][tmp]++;
    return tmp;
}
int gcd(int a, int b)
{
    return b ? gcd(b, a % b) : a;
}
int main()
{
    long long n;
    cin >> n >> m, res[0] = 1;
    for (int i = 1; i <= m; i++) scanf("%s%d", type, &y), x = type[0] - 65, d[x][y] = 1, e[x] = 1;
    for (int i = 0; i < 26; i++)
    {
        s[i] = 1;
        for (int j = 0; j < 123; j++) if (d[i][j]) s[i] *= j / gcd(s[i], j);
        for (int j = 122; j; j--) if (d[i][j])
                for (int k = j; k < 123; k += j) d[i][k] = 1;
        d[i][0] = 1;
    }
    dfs(p);
    while (n)
    {
        if (n & 1) mul1();
        n /= 2;
        mul();
    }
    for (int i = 0; i < now; i++) if (f[i]) ans = (ans + res[i]) % oo;
    printf("%d\n", ans);
    return 0;
}

#include <cstdio>
#include <cstring>
#include <map>
#include <vector>
#include <algorithm>
#include <iostream>
#include <cassert>
using namespace std;
const int MOD=12345;
const int maxm=1010;
map<int,vector<int> > mp;
map<vector<int>,int> inv_mp;
long long n;
int m;
vector<int> b[26],b_size; //val id
int a[maxm],a_size;
int E;
vector<int> c[26],c_size;
pair<string,int> d[maxm]; //A 20
int belong[maxm];
int cnt[26];
int dfs_click;

void inc(int &a,int b)
{
	a+=b;
	if(a>=MOD) a-=MOD;
}

struct Matrix
{
	int mp[130][130];
	int size;
	Matrix(int s)
	{
		size=s;
		zero();
	}
	void zero()
	{
		for(int i=0;i<size;i++)
			for(int j=0;j<size;j++)
				mp[i][j]=0;
	}
	void one()
	{
		for(int i=0;i<size;i++)
			for(int j=0;j<size;j++)
				mp[i][j]=i==j;
	}
	Matrix operator*(const Matrix &A)const
	{
		Matrix ans(A.size);
		ans.zero();
		for(int i=0;i<size;i++)
			for(int j=0;j<size;j++)
				for(int k=0;k<size;k++)
					inc(ans.mp[i][j],mp[i][k]*A.mp[k][j]%MOD);
		return ans;
	}
};

Matrix pow_mod(Matrix a,long long b)
{
	Matrix ans(a.size);
	ans.one();
	while(b)
	{
		if(b&1) ans=ans*a;
		a=a*a;
		b>>=1;
	}
	return ans;
}

void dfs(int cur,vector<int> v)
{
	if(cur==a_size)
	{
		mp[dfs_click]=v;
		inv_mp[v]=dfs_click++;
		return;
	}
	for(int i=0;i<a[cur];i++)
	{
		vector<int> vv=v;
		vv.push_back(i);
		dfs(cur+1,vv);
	}
}

int getN(int u,int k)
{
	vector<int> v=mp[u];
	for(int i:c[k])
    {
        v[i]++;
        v[i]%=a[i];
    }
	assert(inv_mp.find(v)!=inv_mp.end());
	return inv_mp[v];
}

int solve()
{
	for(int i=0;i<m;i++)
		b[d[i].first[0]-'A'].push_back(d[i].second);
	for(int i=0;i<26;i++)
	{
		int s=(int)b[i].size();
		if(!s) continue;
		else
		{
			for(int j:b[i])
			{
				belong[a_size]=E;
				c[E].push_back(a_size);
				a[a_size++]=j;
			}
			E++;
		}
	}
	dfs(0,vector<int>());

	Matrix ans(dfs_click);
	for(int u=0;u<dfs_click;u++)
	{
		for(int j=0;j<E;j++)
        {
            int v=getN(u,j);
            ans.mp[u][v]=1;
        }
	}
	ans=pow_mod(ans,n);
	int res=0;
	for(int i=0;i<dfs_click;i++)
	{
		memset(cnt,0,sizeof(cnt));
		assert(mp.find(i)!=mp.end());
		vector<int> v=mp[i];
		for(int j=0;j<a_size;j++)
		{
			if(v[j]) continue;
			cnt[belong[j]]++;
		}
		int num=0;
		for(int j=0;j<26;j++)
			if(cnt[j])
				num++;
		if(num==E) inc(res,ans.mp[0][i]);
	}
	return res;
}

int main()
{
	//freopen("107D.txt","r",stdin);
	scanf("%I64d %d",&n,&m);
	for(int i=0;i<m;i++)
		cin>>d[i].first>>d[i].second;
	printf("%d\n",solve());
	return 0;
}

#include <map>
#include <cstdio>
#include <vector>
#include <cstring>
using namespace std;
#define ULL unsigned long long
const ULL SEED = 377;
const int MOD = 12345;
int read()
{
    int num=0,flag=1;char c;
    while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    while(c>='0'&&c<='9')num=(num<<3)+(num<<1)+(c^48),c=getchar();
    return num*flag;
}
int m,ans,cnt,t[30];
ULL n,Pow[30]={1},_hash[300];
map<ULL,int> mp;
vector<int> l[30];
struct node
{
	int c[30];
	node() {memset(c,0,sizeof c);}
}a[300],b;
struct Matrix
{
	int n,m,a[300][300];
	Matrix () {n=m=0,memset(a,0,sizeof a);}
	Matrix operator * (const Matrix &B) const
	{
		Matrix res;
		res.n=n,res.m=B.m;
		for(int i=1;i<=n;i++)
			for(int j=1;j<=m;j++)
				for(int k=1;k<=B.m;k++)
					res.a[i][k]=(res.a[i][k]+a[i][j]*B.a[j][k])%MOD;
		return res;
	}
}mat;
void dfs(int x,ULL Hash,node now)
{
	if(x==27)
	{
		mp[Hash]=++cnt;
		_hash[cnt]=Hash;
		a[cnt]=now;
		return ;
	}
	dfs(x+1,Hash*SEED,now);
	for(int i=1;i<t[x];i++)
	{
		now.c[x]=i;
		dfs(x+1,Hash*SEED+i,now);
	}
}
void cal(int x,ULL Hash)
{
	if(x==27)
	{
		ans=(ans+mat.a[1][mp[Hash]])%MOD;
		return ;
	}
	if(t[x]==0) cal(x+1,Hash*SEED);
	for(int i=0;i<t[x];i++)
	{
		bool flag=0;
		for(int j=0;j<l[x].size();i++)
			if(i%l[x][j]==0)
			{
				flag=1;
				break;
			}
		if(flag)
			cal(x+1,Hash*SEED+i);
	}
}
Matrix ksm(Matrix A,ULL b)
{
	Matrix res;
	res.n=res.m=A.n;
	for(int i=1;i<=A.n;i++)
		res.a[i][i]=1;
	while(b>0)
	{
		if(b&1) res=res*A;
		A=A*A;
		b>>=1;
	}
	return res;
}
int main()
{
	scanf("%llu",&n);m=read();
	if(n==0)
    {
        printf("1\n");
        return 0;
    }
    if(m==0)
    {
        printf("0\n");
        return 0;
    }
	for(int i=1;i<=26;i++)
		Pow[i]=Pow[i-1]*SEED;
	for(int i=1;i<=m;i++)
	{
		char c;scanf("%s",&c);
		int u=c-'A'+1,x=read();
		if(!t[u]) t[u]=x;
		else t[u]*=x;
		l[u].push_back(x);
	}
	dfs(1,0,b);
	for(int i=1;i<=cnt;i++)
	{
		for(int j=1;j<=26;j++)
		{
			if(t[j]==0) continue;
			ULL to=_hash[i]+Pow[26-j];
			if(a[i].c[j]==t[j]-1)
				to-=t[j]*Pow[26-j];
			mat.a[i][mp[to]]++;
		}
	}
	mat.n=mat.m=cnt;
	mat=ksm(mat,n);
	cal(1,0);
	printf("%d\n",ans);
}

#include<cstdio>
#include<iostream>
#include<string>
#include<cstring>
#include<algorithm>
#include<vector>
using namespace std;

struct matrix
{int a[130][130];
};
struct matrix g,f,e;

struct unit
{int x;
 vector<int> w;
};
struct unit a[30];

long long n;
int m,ans;
int b[30],c[30];
const int mod=12345;

bool cmp(struct unit aa,struct unit bb)
{return aa.x>bb.x;
}

int gcd(int i,int j)
{if(j==0)
    return i;
 else
    return gcd(j,i%j);
}

matrix operator *(matrix aa,matrix bb)
{matrix ret;
 int i,j,k;
 memset(ret.a,0,sizeof(ret.a));
 for(i=0;i<=123;i++)
    for(j=0;j<=123;j++)
    {   for(k=0;k<=123;k++)
        {   ret.a[i][j]=(ret.a[i][j]+aa.a[i][k]*bb.a[k][j]);
            if(k&7==0)
                ret.a[i][j]%=mod;
        }
        ret.a[i][j]%=mod;
    }
 return ret;
}

matrix fpow(long long j)
{matrix ret=e,t;
 t=g;
 while(j>0)
 {  if(j&1) ret=ret*t;
    t=t*t;
    j/=2;
 }
 return ret;
}

int main()
{int i,j,x,s,s1,flag;
 char ch[2];
 for(i=0;i<=123;i++)
    e.a[i][i]=1;
 scanf("%I64d%d",&n,&m);
 for(i=1;i<=m;i++)
 {  scanf("%s%d",ch,&x);
    if(a[ch[0]-64].x==0)
        a[ch[0]-64].x=x;
    else
        a[ch[0]-64].x=a[ch[0]-64].x*x/gcd(a[ch[0]-64].x,x);
    a[ch[0]-64].w.push_back(x);
 }
 sort(a+1,a+26+1,cmp);
 for(i=1;i<=26;i++)
    if(a[i].x==0)
    {   m=i-1;
        break;
    }
 for(i=m;i>=1;i--)
 {  b[i]=1;
    for(j=i+1;j<=m;j++)
        b[i]+=(a[j].x-1)*b[j];
 }
 while(c[0]==0)
 {  s=0;
    for(i=1;i<=m;i++)
        s+=c[i]*b[i];
    for(i=1;i<=m;i++)
    {   if(c[i]==a[i].x-1)
            s1=s-b[i]*(a[i].x-1);
        else
            s1=s+b[i];
        g.a[s][s1]++;
    }
    i=m;
    while(c[i]==a[i].x-1)
    {   c[i]=0;
        i--;
    }
    c[i]++;
 }
 f=fpow(n);
 memset(c,0,sizeof(c));
 while(c[0]==0)
 {  s=0;
    flag=1;
    for(i=1;i<=m;i++)
        s+=c[i]*b[i];
    for(i=1;i<=m;i++)
    {   flag=0;
        for(j=0;j<a[i].w.size();j++)
            if(c[i]%a[i].w[j]==0)
            {   flag=1;
                break;
            }
        if(!flag) break;
    }
    if(flag) ans=(ans+f.a[0][s])%mod;
    i=m;
    while(c[i]==a[i].x-1)
    {   c[i]=0;
        i--;
    }
    c[i]++;
 }
 cout<<ans<<endl;
 return 0;
}

#include <stdio.h>
#include <string.h>
#define MOD 12345
#define MaxN 128

int a[MaxN][MaxN], b[MaxN][MaxN], c[MaxN][MaxN], v[32], p[32], N;

void Mul(int a[MaxN][MaxN], int b[MaxN][MaxN])
{
    memset(c, 0, sizeof(c));
    for (int k = 0; k < N; ++k)
        for (int i = 0; i < N; ++i) if (a[i][k])
            for (int j = 0; j < N; ++j) if (b[k][j])
                c[i][j] = (c[i][j]+a[i][k]*b[k][j]) % MOD;
    memcpy(a, c, sizeof(c));
}

int main()
{
    long long L;
    int m, t;
    char ch;

    while (scanf("%I64d%d", &L, &m) != EOF) {
        memset(v, 0, sizeof(v));
        memset(b, 0, sizeof(b));
        while (m--) {
            scanf(" %c%d", &ch, &t); ch -= 'A';
            if (!v[ch] || t < v[ch]) v[ch] = t;
        }
        int n = 0;
        p[0] = 1;
        for (int i = 0; i < 26; ++i) if (v[i]) v[n++] = v[i];
        for (int i = 1; i <= n; ++i) p[i] = p[i-1]*v[i-1];
        N = p[n];
        for (int i = 0; i < N; ++i) {
            for (int j = 0; j < n; ++j) {
                int d = i%p[j+1]/p[j], nd = d + 1;
                if (nd == v[j]) nd = 0;
                int ni = i+p[j]*(nd-d);
                ++b[ni][i];
            }
        }
        for (int i = 0; i < N; ++i) for (int j = 0; j < N; ++j) a[i][j] = i==j;
        for (; L; L >>= 1, Mul(b, b)) if (L&1) Mul(a, b);
        printf("%d\n", a[0][0]);
    }
    return 0;
}

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

const int mod = 12345;

int num[30],p[30][1010];

char str[1010][10];

int g[130][130],tmp[130][130],ans[130][130];

int now[1010],x[1010];

int tot,m;

void power(int y)
{
    int i,j,k;
    memset(ans,0,sizeof(ans));
    for(i=0;i<tot;i++)
        ans[i][i]=1;
    while(y)
    {
        if(y&1)
        {
            memset(tmp,0,sizeof(tmp));
            for(i=0;i<tot;i++)
                for(j=0;j<tot;j++)
                    for(k=0;k<tot;k++)
                        tmp[i][j]=(tmp[i][j]+ans[i][k]*g[k][j])%mod;
            for(i=0;i<tot;i++)
                for(j=0;j<tot;j++)
                    ans[i][j]=tmp[i][j];
        }
        memset(tmp,0,sizeof(tmp));
        for(i=0;i<tot;i++)
            for(j=0;j<tot;j++)
                for(k=0;k<tot;k++)
                    tmp[i][j]=(tmp[i][j]+g[i][k]*g[k][j]);
        for(i=0;i<tot;i++)
            for(j=0;j<tot;j++)
                g[i][j]=tmp[i][j];
        y/=2;
    }
    return;
}

bool check(int y)
{
    int temp=y,i,j,flag;
    for(i=0;i<m;i++)
    {
        now[i]=temp%x[i];
        temp/=x[i];
    }
    for(i=0;i<26;i++)
    {
        flag=0;
        if(num[i]==0)
            continue;
        for(j=0;j<m;j++)
        {
            if(str[j][0]-'A'==i&&now[j]==0)
            {
                flag=1;
                break;
            }
        }
        if(flag==0)
            return false;
    }
    return true;
}

int main()
{
    int n,i,j,temp,k;
    tot=1;
    scanf("%d%d",&n,&m);
    memset(num,0,sizeof(num));
    for(i=0;i<m;i++)
    {
        scanf("%s%d",str[i],&x[i]);
        p[str[i][0]-'A'][++num[str[i][0]-'A']]=x[i];
        tot=tot*x[i];
    }
    memset(g,0,sizeof(g));
    for(i=0;i<tot;i++)
    {
      //  printf("%d %d\n",i,tot);
        temp=i;
        for(j=0;j<m;j++)
        {
            now[j]=temp%x[j];
            temp/=x[j];
       //     printf("fuck %d %d %d\n",i,j,now[j]);
        }
        for(j=0;j<26;j++)
        {
            if(num[j]==0)
                continue;
            for(k=0;k<m;k++)
            {
                if(str[k][0]-'A'==j)
                    now[k]=(now[k]+1)%x[k];
            }
            temp=0;
            for(k=m-1;k>=0;k--)
            {
                temp=temp*x[k];
                temp=temp+now[k];
            }
            g[temp][i]=1;
            for(k=0;k<m;k++)
            {
                if(str[k][0]-'A'==j)
                    now[k]=(now[k]-1+x[k])%x[k];
            }
        }
    }
/*
    for(i=0;i<tot;i++)
    {
        for(j=0;j<tot;j++)
            printf("%d ",g[i][j]);
        printf("\n");
    }
*/
    power(n);
/*
    for(i=0;i<tot;i++)
    {
        for(j=0;j<tot;j++)
            printf("%d ",ans[i][j]);
        printf("\n");
    }
*/
    int final=0;
    for(i=0;i<tot;i++)
    {
        if(check(i))
            final=(final+ans[0][i])%mod;
    }
    printf("%d\n",final);
    return 0;
}

#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
using namespace std;
typedef long long LL;
const int P=12345;
const int maxn=130;
int n,N,A[maxn];
bool B[maxn][maxn];

struct Tmtx{
    int a[maxn][maxn];int n;
    Tmtx(){}
    Tmtx(int _n,bool x=0){
        int i;n=_n,memset(a,0,sizeof a);
        for(i=0;i<n;++i)a[i][i]=x;
    }
    Tmtx Tpose()const{
        Tmtx b;register int i,j;
        for(i=0;i<n;++i)
        for(j=0;j<n;++j)b.a[i][j]=a[j][i];
        return b;
    }
    Tmtx operator *(const Tmtx &b)const{
        Tmtx c(n,0);register int k,i,j;
        for(i=0;i<n;++i)
        for(j=0;j<n;++j)
        for(k=0;k<n;++k)
            c.a[i][j]=(c.a[i][j]+a[i][k]*b.a[k][j])%P;
        return c;
    }
    bool operator ==(const Tmtx &b)const{
        register int i,j;
        for(i=0;i<n;++i)
        for(j=0;j<n;++j)
            if(a[i][j]!=b.a[i][j])return false;
        return true;
    }
    void print(){
        int i,j;
        for(i=0;i<n;++i){
            for(j=0;j<n;++j)cerr<<a[i][j]<<' ';
            cerr<<endl;
        }
    }
};
Tmtx pow(Tmtx x,LL k){
    Tmtx Fc=Tmtx(x.n,1);
    for(;k;k>>=1)k&1?Fc=Fc*x:0,x=x*x;
    return Fc;
}

namespace Ninit{
    char s[10];
    void init(){
        int ni,ai,i,j;
        cin>>n>>ni;
        for(i=0;i<26;++i)A[i]=1;
        for(i=0;i<ni;++i){
            scanf("%s%d",s,&ai),A[s[0]-'A']*=ai;
            for(j=0;j<123;++j)B[i][j]|=(j%ai==0);
        }
    }
}

namespace Nsolve{
    Tmtx An,A0;
    int pw[maxn],ans;
    void solve(){
        int i,j,k,xi,flag;
        for(pw[0]=1,i=1;i<=26;++i)pw[i]=pw[i-1]*A[i-1];
        An.n=A0.n=N=pw[26];
        for(i=0;i<N;++i){
            for(k=0;k<26;++k)if(B[k][0]){
                xi=i/pw[k]%A[k];
                ++A0.a[i][i-xi*pw[k]+(xi+1)%A[k]*pw[k]];
            }
        }
        An=pow(A0,n);
        for(i=0;i<N;++i){
            for(flag=0,k=0;k<26;++k){
                if(!B[k][0])continue;
                if(!B[k][i/pw[k]%A[k]])flag=1;
            }
            if(!flag)ans=(ans+An.a[0][i])%P;
        }
        cout<<ans<<endl;
    }
}

int main(){
    Ninit::init();
    Nsolve::solve();
    return 0;
}

#include<cstdio>
#include<cstring>
#include<vector>
#include<map>
using namespace std;
const int N=155,oo=12345;
int n,m,x,y,now,ans,a[N][N],b[N][N],c[N],e[N],s[N],res[N];
bool d[N][N],f[N];
char type[5];
vector<int > p(26);
map<vector<int >,int > h;
void mul1()
{
	memset(c,0,sizeof(c));
	for (int i=0;i<now;i++)
		for (int j=0;j<now;j++)
			c[i]=(a[i][j]*res[j]+c[i])%oo;
	memcpy(res,c,sizeof(res));
}
void mul()
{
	memset(b,0,sizeof(b));
	for (int i=0;i<now;i++)
		for (int j=0;j<now;j++)
			for (int k=0;k<now;k++)
				b[i][j]=(a[i][k]*a[k][j]+b[i][j])%oo;
	memcpy(a,b,sizeof(a));
}
int dfs(vector<int > c)
{
	typeof(h.end()) it=h.find(c); if (it!=h.end()) return it->second;
	int tmp=now++; h[c]=tmp; f[tmp]=1; vector<int > b;
	for (int i=0;i<26;i++) if (e[i]) f[tmp]&=d[i][c[i]];
	for (int i=0;i<26;i++) if (e[i]) b=c,b[i]=(b[i]+1)%s[i],a[tmp][dfs(b)]=1;
	return tmp;
}
int gcd(int a,int b){return b?gcd(b,a%b):a;}
int main()
{
	scanf("%d%d",&n,&m),res[0]=1;
	for (int i=1;i<=m;i++) scanf("%s%d",type,&y),x=type[0]-65,d[x][y]=1,e[x]=1;
	for (int i=0;i<26;i++){
		s[i]=1; for (int j=0;j<123;j++) if (d[i][j]) s[i]*=j/gcd(s[i],j);
		for (int j=122;j;j--) if (d[i][j])
			for (int k=j;k<123;k+=j) d[i][k]=1;
		d[i][0]=1;
		}
	dfs(p); while (n){if (n&1) mul1(); n/=2; mul();}
	for (int i=0;i<now;i++) if (f[i]) ans=(ans+res[i])%oo;
	printf("%d\n",ans); return 0;
}

#include <iostream>
#include <cstdio>
#include <vector>
#include <map>
#include <set>
#include <utility>
#include <cstring>
#define MOD 12345
using namespace std;
#define pb(a) push_back(a)
#define fi first
#define se second
typedef pair<int,int> pii;
typedef pair<char,pii> data;
vector<data> rules,tmp;
set<char> EQ,BAN;
long long n;
int c,M;
typedef map< vector<data> , int > STATE;
typedef map< int , vector<data> > REV;
STATE states;
REV rev;
void gen_all_states(int p){
  if(p==rules.size()){states.insert(make_pair(tmp,0)); return;}
  tmp.pb(rules[p]);
  for(int i=0;i<tmp.back().se.fi;++i){
   tmp.back().se.se=i;
   gen_all_states(p+1);
                                     }
  tmp.pop_back();
}
int GO(vector<data>& w , char C){
  for(int i=0;i<w.size();++i)
   if(w[i].fi==C){++w[i].se.se; if(w[i].se.se>=w[i].se.fi)w[i].se.se=0;}
  int ret=states[w];
  for(int i=0;i<w.size();++i)
   if(w[i].fi==C){--w[i].se.se; if(w[i].se.se<0)w[i].se.se=w[i].se.fi-1;}
  return ret;
}
// MATRIX SOLUTION
typedef long long ll;
struct MATR{
  ll D[200][200];
  MATR(){memset(D,0,sizeof D);}
  void ONE(){for(int i=0;i<M;++i)D[i][i]=1;}
  MATR operator*(MATR& w){
   MATR ret;
   for(int i=0;i<M;++i)
    for(int j=0;j<M;++j)
     for(int k=0;k<M;++k)
      ret.D[i][j]+=D[i][k]*w.D[k][j];
   for(int i=0;i<M;++i)
    for(int j=0;j<M;++j)ret.D[i][j]%=MOD;
   return ret;
                         }
};
MATR B;
MATR POW(ll step){
  MATR ret; ret.ONE();
  for(;step;step>>=1,B=B*B)
   if(step&1)ret=B*ret;
  return ret;
}
// FINAL
int CU[300],ust;
bool OK(vector<data> w){
  ++ust;
  for(int i=0;i<w.size();++i)
   if(!w[i].se.se)CU[w[i].fi]=ust;
  for(int i=0;i<w.size();++i)
   if(CU[w[i].fi]!=ust)return false;
  return true;
}
int main(){
  cin>>n>>c;
  if(n==0){cout<<1<<'\n'; return 0;}
  for(char i='A';i<='Z';++i)BAN.insert(i);
  for(int i=0;i<c;++i){
   char D; int br;
   cin>>D>>br;
   BAN.erase(D);
   if(br==1)EQ.insert(D);
   else tmp.pb(data(D,pii(br,0)));
                      }
  for(int i=0;i<tmp.size();++i)
   if(EQ.count(tmp[i].fi))continue;
   else rules.pb(tmp[i]);
  tmp.clear();
  // when rules are empty?
  if(rules.empty())
   rules.pb(data('?',pii(1,0)));
  gen_all_states(0);
  for(STATE::iterator it=states.begin();it!=states.end();++it){
   it->se=M++;
   rev[it->se]=it->fi;
                                                              }
  for(STATE::iterator it=states.begin();it!=states.end();++it){
   vector<data> USE=it->fi;
   for(char C='A';C!='Z';++C)
    if(!BAN.count(C))++B.D[it->se][GO(USE,C)];
                                                              }
  B=POW(n);
  int START=states[rules];
  ll ans=0;
  for(int i=0;i<M;++i)
   if(OK(rev[i]))ans+=B.D[START][i];
  ans%=MOD;
  cout<<ans<<'\n';
  //system("pause");
  return 0;
}

#include<iostream>
#include<cstdio>
#include<vector>
#include<cmath>
#define mod 12345
using namespace std;
long long res;
struct node
{
  long long W[123];
};
node c,ans,tans,e,w[123];
long long MOD;
struct complex
{
	double x,y;
};
const long double Pi=asin(1)*2;
complex A[5032],B[5032],Ans[5032],wn;
complex operator + (complex a,complex b)
{
	return complex{a.x+b.x,a.y+b.y};
}
complex operator - (complex a,complex b)
{
	return complex{a.x-b.x,a.y-b.y};
}
complex operator *(complex a,complex b)
{
	return complex{a.x*b.x-a.y*b.y,a.x*b.y+b.x*a.y};
}
void FFT(int limit,complex *s,int type)
{
	if (limit==1)
		return;
	complex a2[limit/2+1],b2[limit/2+1];
	for (int i=0;i<limit;i+=2)
	{
		a2[i/2]=s[i];
		b2[i/2]=s[i+1];
	}
	FFT(limit/2,a2,type);
	FFT(limit/2,b2,type);
	complex w;
	w=complex{cos(2*Pi/limit),type*sin(2*Pi/limit)},wn=complex{1,0};
	for (int i=0;i<limit/2;++i,wn=wn*w)
	{
		s[i]=a2[i]+wn*b2[i];
		s[i+limit/2]=a2[i]-wn*b2[i];
	}
	return;
}
node operator * (node a,node b)
{
  int limit=1;
  while (limit<=2*res)
  	limit*=2;
  for (int i=0;i<=limit;++i)
    A[i]=B[i]=Ans[i]=(complex){0,0};
  for (int i=0;i<res;++i)
  	A[i].x=a.W[i],B[i].x=b.W[i];
  FFT(limit,A,1),FFT(limit,B,1);
  for (int i=0;i<=limit;++i)
  	Ans[i]=A[i]*B[i];
  FFT(limit,Ans,-1);
  for (int i=0;i<limit;++i)
  	 Ans[i].x=(long long)(Ans[i].x/limit+0.5);
  for (int i=0;i<res;++i)
     c.W[i]=((long long)(Ans[i].x)+(long long)(Ans[res+i].x))%MOD;
  return c;
}
node operator + (node a,node b)
{
  for (int i=0;i<res;++i)
    c.W[i]=(a.W[i]+b.W[i])%MOD;
  return c;
}
node operator - (node a,node b)
{
  for (int i=0;i<res;++i)
    c.W[i]=(a.W[i]-b.W[i])%MOD;
  return c;
}
node fast_pow(node a,long long b)
{
  if (b==0)
    return e;
  if (b&1)
    return fast_pow(a*a,b/2)*a;
  else
    return fast_pow(a*a,b/2);
}
char x;
long long n,C,y,dp[27][124],F[27][124],cnt[27];
vector<int>p[28];
long long read()
{
  char c=0;
  long long sum=0;
  while (c<'0'||c>'9')
    c=getchar();
  while ('0'<=c&&c<='9')
    sum=sum*10+c-'0',c=getchar();
  return sum;
}
int gcd(int x,int y)
{
  if (y==0)
    return x;
  return gcd(y,x%y);
}
int lcm(int x,int y)
{
  return x*y/gcd(x,y);
}
node tmp;
void dfs(int t,long long mul)
{
  if (t==26)
    {
      tmp=fast_pow(tans,n);
      for (int i=0;i<res;++i)
		tmp.W[i]=tmp.W[i]*mul%MOD;
      ans=ans+tmp;
      return;
    }
  if (!p[t].size())
    {
      dfs(t+1,mul);
      return;
    }
  for (int i=0;i<res;++i)
    if (F[t][i])
      tans=tans+w[i],dfs(t+1,mul*F[t][i]%MOD),tans=tans-w[i];
  return;
}
int main()
{
  n=read(),C=read();
  res=1;
  for (int i=1;i<=C;++i)
    {
      cin>>x,y=read();
      p[x-'A'].push_back(y),res=lcm(res,y);
    }
  e.W[0]=1;
  for (int i=0;i<res;++i)
    w[i].W[i]=1;
  MOD=mod;
  for (int i=0;i<26;++i)
    {
      cnt[i]=1;
      for (int j=0;j<p[i].size();++j)
	cnt[i]=lcm(cnt[i],p[i][j]);
      MOD*=cnt[i];
    }
  for (int i=0;i<26;++i)
    if (p[i].size())
      {
	dp[i][1]=-1;
	for (int j=0;j<p[i].size();++j)
	  for (int s=res;s>=1;--s)
	  	if (dp[i][s])
	  	  dp[i][lcm(s,p[i][j])]-=dp[i][s];
	dp[i][1]++;
	for (int s=1;s<=res;++s)
	  if (cnt[i]%s==0)
	    {
	      for (int t=0;t<res;t+=res/s)
		F[i][t]=(F[i][t]+dp[i][s]*(cnt[i]/s)%MOD)%MOD;
	    }
      }
  dfs(0,1);
  int ts;
  for (int i=1;i<res;++i)
    if (res%i==0)
      {
	ts=ans.W[i];
	for (int j=0;j<res;j+=i)
	  ans.W[j]=(ans.W[j]-ts)%MOD;
      }
  ans.W[0]=(ans.W[0]+MOD)%MOD;
  for (int i=0;i<26;++i)
     ans.W[0]/=cnt[i];
  printf("%lld\n",(ans.W[0]+mod)%mod);
  return 0;
}

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<map>
#include<vector>
#include<algorithm>

using namespace std;

const int mo=12345;

int s,cnt,num,multi[30],c,pos[30];

long long n;

char st[3];

vector<int> status[125],nowway,v[30];

map< vector <int> , int > id;

struct matrix
{
	int z[125][125];
	matrix()
	{
		memset(z,0,sizeof(z));
	}
	matrix operator*(const matrix &a)const
	{
		matrix ans;
		for (int b=1;b<=s;b++)
			for (int c=1;c<=s;c++)
				for (int d=1;d<=s;d++)
					ans.z[b][c]=(ans.z[b][c]+z[b][d]*a.z[d][c]%mo)%mo;
		return ans;
	}
}m1,m2;

matrix mul(matrix a,long long b)
{
	matrix ans;
	for (int c=1;c<=s;c++)
		ans.z[c][c]=1;
	while (b)
	{
		if (b&1) ans=ans*a;
		a=a*a;
		b>>=1;
	}
	return ans;
}

void dfs(int now)
{
	if (now==cnt)
	{
		num++;
		status[num]=nowway;
		id[nowway]=num;
	}
	else
	{
		for (int a=0;a<multi[now];a++)
		{
			nowway.push_back(a);
			dfs(now+1);
			nowway.pop_back();
		}
	}
}

int gcd(int a,int b)
{
	if (a % b==0) return b;
	else return a;
}

int main()
{
	scanf("%I64d%d",&n,&c);
	for (int a=1;a<=c;a++)
	{
		scanf("%s",st);
		int nowv;
		scanf("%d",&nowv);
		v[st[0]-'A'+1].push_back(nowv);
	}
	s=1;
	for (int a=1;a<=26;a++)
		if (v[a].size())
		{
			sort(v[a].begin(),v[a].end());
			v[a].resize(unique(v[a].begin(),v[a].end())-v[a].begin());
			int size=0;
			for (int b=0;b<(int)v[a].size();b++)
			{
				bool able=true;
				for (int c=0;c<b;c++)
					if (v[a][b]%v[a][c]==0) able=false;
				if (able)
				{
					v[a][size]=v[a][b];
					size++;
				}
			}
			v[a].resize(size);
			if (v[a].back()==1) continue;
			int lcm=1;
			for (int b=0;b<(int)v[a].size();b++)
				lcm=lcm*v[a][b]/gcd(v[a][b],lcm);
			s*=lcm;
			multi[cnt]=lcm;
			pos[a]=cnt;
			cnt++;
		}
	dfs(0);
	for (int a=1;a<=num;a++)
	{
		nowway=status[a];
		for (int b=1;b<=26;b++)
			if (v[b].size())
			{
				if (v[b].back()==1) m1.z[a][a]++;
				else
				{
					nowway[pos[b]]++;
					nowway[pos[b]]%=multi[pos[b]];
					int idx=id[nowway];
					m1.z[a][idx]++;
					nowway[pos[b]]+=multi[pos[b]]-1;
					nowway[pos[b]]%=multi[pos[b]];
				}
			}
	}
	m2.z[1][1]=1;
	m2=m2*mul(m1,n);
	int ans=0;
	for (int a=1;a<=num;a++)
	{
		nowway=status[a];
		bool able=true;
		for (int b=1;b<=26;b++)
			if (v[b].size())
			{
				if (v[b].back()==1) continue;
				bool fail=true;
				for (int c=0;c<(int)v[b].size();c++)
					if (nowway[pos[b]]%v[b][c]==0)
					{
						fail=false;
						break;
					}
				if (fail)
				{
					able=false;
					break;
				}
			}
		if (able) ans=(ans+m2.z[1][a])%mo;
	}
	printf("%d\n",ans);

	return 0;
}

#include <cstdio>
#include <vector>
using namespace std;
#define rep(i,n) for (int i=0;i<n;i++)
typedef int matrix[130][130];
long long n;
vector<int> v[30];
int k,q[30],d,f[30],h[130],len[30],r[30],ans;
matrix a,b,t;char c;
int gcd(int a,int b) {return b?gcd(b,a%b):a;}
void mul(matrix a,matrix b) {
	rep(i,len[0]) rep(j,len[0]) {
		t[i][j]=0;
		rep(k,len[0]) t[i][j]=(t[i][j]+a[i][k]*b[k][j])%12345;
	}
	rep(i,len[0]) rep(j,len[0]) a[i][j]=t[i][j];
}
void pow(long long n) {
	rep(i,len[0]) a[i][i]=1;
	for (int i=0;n>>i;i++) {
		if ((n>>i)&1) mul(a,b);
		mul(b,b);
	}
}
int main() {
	scanf("%I64d%d",&n,&k);
	rep(i,26) q[i]=1;
	rep(i,k) scanf(" %c%d",&c,&d),c-='A',q[c]*=d/gcd(d,q[c]),
		f[c]=1,v[c].push_back(d);
	len[26]=1;
	for (int j=25;j>=0;j--) len[j]=len[j+1]*q[j];
	rep(j,len[0]) {
		rep(i,26) r[i]=j/len[i+1]%q[i];h[j]=1;
		rep(i,26) if (v[i].size()) {
			bool fg=0;
			for (int d:v[i]) fg|=(r[i]%d==0);
			h[j]&=fg;
		}
		rep(i,26) if (f[i]) b[j][(r[i]+1==q[i])?j+len[i+1]-len[i]:j+len[i+1]]++;
	}
	rep(i,len[0]) rep(j,len[0]) if (b[i][j]) printf("%d %d %d\n",i,j,b[i][j]);
	rep(i,len[0]) if (h[i]) printf("%d\n",i);
	pow(n);
	rep(i,len[0]) ans+=h[i]*a[0][i];
	printf("%d\n",ans);
}

#include <bits/stdc++.h>

using namespace std;

typedef long long ll;
const int M = 12345;

int add(int a, int b) {
  a += b;
  if (a >= M) {
    return a - M;
  }
  if (a < 0) {
    return a + M;
  }
  return a;
}

int mul(int a, int b) {
  return a * (ll) b % M;
}

ll n;
int q;
vector<int> g[26];
int p[26];
vector<vector<int>> good;
vector<int> prods;
int sz;
int pall = 1;
int go[123][123];

int get(vector<int> a) {
  int sol = 0;
  for (int i = 0; i < sz; i++) {
    sol = sol * prods[i] + a[i];
  }
  return sol;
}

vector<int> get(int x) {
  vector<int> sol;
  for (int i = sz - 1; i >= 0; i--) {
    sol.push_back(x % prods[i]);
    x /= prods[i];
  }
  reverse(sol.begin(), sol.end());
  return sol;
}

void print(vector<int> a) {
  cout << " : ";
  for (auto &x : a) {
    cout << x << " ";
  }
  cout << "\n";
}

vector<int> operator * (vector<int> a, vector<int> b) {
  vector<int> c(pall, 0);
  for (int i = 0; i < pall; i++) {
    for (int j = 0; j < pall; j++) {
      int k = go[i][j];
      c[k] = add(c[k], mul(a[i], b[j]));
    }
  }
  return c;
}

int main() {
  ios::sync_with_stdio(false);
  cin.tie(0);
  cin >> n >> q;
  if (q == 0) {
    cout << "0\n";
    return 0;
  }
  while (q--) {
    string s;
    int x;
    cin >> s >> x;
    int i = s[0] - 'A';
    if (p[i] == 0) {
      p[i] = 1;
    }
    g[i].push_back(x);
    p[i] *= x;
  }
  for (int i = 0; i < 26; i++) {
    if (p[i]) {
      good.push_back(g[i]);
      prods.push_back(p[i]);
      sz++;
    }
  }
  pall = 1;
  for (auto &it : prods) {
    pall *= it;
  }
  for (int i = 0; i < pall; i++) {
    for (int j = 0; j < pall; j++) {
      vector<int> a = get(i), b = get(j);
      vector<int> c(sz);
      for (int k = 0; k < sz; k++) {
        c[k] = (a[k] + b[k]) % prods[k];
      }
      go[i][j] = get(c);
    }
  }
  vector<int> zero(sz, 0);
  vector<int> sol(pall, 0), cur(pall, 0);
  sol[0] = 1;
  for (int i = 0; i < sz; i++) {
    vector<int> alpha = zero;
    alpha[i] = 1 % prods[i];
    cur[get(alpha)] = 1;
  }
  for (int p = 0; (1LL << p) <= n; p++) {
    if (n & (1LL << p)) {
      sol = sol * cur;
    }
    cur = cur * cur;
  }
  int ans = 0;
  for (int i = 0; i < pall; i++) {
    vector<int> a = get(i);
    bool oke = 1;
    for (int k = 0; k < sz; k++) {
      oke = 0;
      for (auto &it : good[k]) {
        if (a[k] % it == 0) {
          oke = 1;
          break;
        }
      }
      if (oke == 0) {
        break;
      }
    }
    if (oke) {
      ans = add(ans, sol[i]);
    }
  }
  return 0;
}

#include <algorithm>
#include <iostream>
#include <cstdio>
#include <vector>
#include <cmath>
#include <set>
#include <map>
using namespace std;

#define F first
#define S second
#define P_B push_back
#define size(x) (int)x.size()
#define all(x) x.begin(), x.end()
#define FR(i, a, b) for(int i = a; i < b; i++)
#define ROF(i, a, b) for(int i = a; i >= b; i--)
#define debug(x) cerr<< #x << ": " << x << endl;
#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);

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

const int mod = 12345;
//const int MAXN = 1000 * 1000 + 10;
vector <int> vec, v;
map <vector <int>, int> mp;
int t[50], cnt = 0, m;
bool mark[50][200];
ll mat[200][200], mat2[200][200];

void f(ll n)
{
	if(n == 1)
		return;
	f(n / 2);

	ll temp[200][200];
	FR(i, 0, cnt)
		FR(j, 0, cnt)
		{
			temp[i][j] = 0;
			FR(k, 0, cnt)
				temp[i][j] = (temp[i][j] + mat[i][k] * mat[k][j]) % mod;
		}

	FR(i, 0, cnt)
		FR(j, 0, cnt)
			mat[i][j] = temp[i][j];

	if(n % 2 == 1)
	{
		FR(i, 0, cnt)
			FR(j, 0, cnt)
			{
				temp[i][j] = 0;
				FR(k, 0, cnt)
					temp[i][j] = (temp[i][j] + mat[i][k] * mat2[k][j]) % mod;

			}

	FR(i, 0, cnt)
		FR(j, 0, cnt)
			mat[i][j] = temp[i][j];
	}

}

void make(int ind)
{
	if(ind == m)
	{
		mp[v] = cnt++;
		return;
	}

	FR(i, 0, t[vec[ind]])
	{
		v[ind] = i;
		make(ind + 1);
	}
}

int main()
{
	fast;
	ll n, c;
	cin>> n >> c;

	FR(i, 0, c)
	{
		char a;
		int b;
		cin>> a >> b;
		if(t[a - 'A'] == 0)
		{
			t[a - 'A'] = b;
			vec.P_B(a - 'A');
			mark[a - 'A'][0] = true;
		}
		else
			t[a - 'A'] *= b;
		mark[a - 'A'][b] = true;
	}

	m = size(vec);
	if(n == 0)
	{
		cout<< 1 << endl;
		return 0;
	}
	else if(n == 1)
	{
		int o = 0;
		FR(i, 0, m)
			if(mark[vec[i]][1])
				o++;
		cout<< o << endl;
		return o;
	}

	FR(i, 0, m)
		v.P_B(0);

	make(0);

	for(auto u: mp)
		FR(i, 0, size(u.F))
		{
			vector <int> x = u.F;
			x[i] = (x[i] + 1) % t[vec[i]];
			mat[u.S][mp[x]]++;
		}

	FR(i, 0, cnt)
		FR(j, 0, cnt)
			mat2[i][j] = mat[i][j];

	f(n);
	ll ans = 0;
	for(auto u: mp)
	{
		bool chck = true;
		FR(i, 0, size(u.F))
		{
			bool ch = false;
			FR(k, 1, 200)
				if(mark[vec[i]][k] && u.F[i] % k == 0)
					ch = true;
			chck = chck & ch;
		}
		if(chck)
			ans += mat[0][u.S];
	}

	cout<< ans << endl;

	return 0;
}

#pragma comment(linker, "/STACK:60000000")
//#define _MY_OPT_MODE_
#define _CRT_SECURE_NO_WARNINGS
#define _CRT_SECURE_NO_DEPRECATE

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <string>
#include <cmath>
#include <algorithm>

#include <vector>
#include <set>
#include <map>
#include <bitset>
#include <queue>
#include <stack>
#include <list>

#include <ctime>
#include <cassert>

using namespace std;

typedef long double ldb;
typedef long long int64;
typedef pair <int, int> pii;

#define div sdfjh
#define y0 wwwwwww
#define y1 qqqqqqq
#define next NEXT
#define prev PREV
#define forn(i, n) for (int i = 0; i < (int) n; i++)
#define ford(i, n) for (int i = (int) n - 1; i >= 0; i--)
#define seta(a, b) memset(a, b, sizeof(a))
#define pb push_back
#define all(a) (a).begin(), (a).end()
#define last(a) a[a.size() - 1];
#define mp make_pair
#define fs first
#define sc second
#define I (int)

template <class T> T sqr(T x) { return x * x; }

double const pi = 3.1415926535897932384626433832795;
int const inf = (int) 1e9 + 1;
int64 const inf64 = (int64) 4e18 + 1;
const string name = "d";

const int NMAX = 128;
const int P = 12345;

int64 n;
int m, K, k[256], zn[NMAX], used[NMAX];
char ch[NMAX];
vector <int> div[NMAX];
vector < pair <char, int> > value[NMAX];
map <vector < pair <char, int> >, int> num;
int res[NMAX][NMAX], a[NMAX][NMAX], q[NMAX][NMAX];

int gcd(int a, int b)
{
	if (a * b == 0) return a + b;
	else return gcd(b % a, a);
}

vector < pair <char, int> > now;

void rec(int x)
{
	if (x == 256)
	{
		num[now] = K;
		value[K] = now;
		K++;
		return;
	}
	if (!used[x])
		rec(x + 1);
	else
	{
		forn(i, k[x])
		{
			now.pb(mp((char) x, i));
			rec(x + 1);
			now.pop_back();
		}
	}
}

int main()
{
#ifndef ONLINE_JUDGE
	freopen((name + ".in").data(), "r", stdin);
	freopen((name + ".out").data(), "w", stdout);
#endif

	forn(i, 256)
	{
		used[i] = 0;
		k[i] = 1;
	}
	cin >> n >> m;
	if (n == 0 || m == 0)
	{
		cout << 0 << endl;
		return 0;
	}
	forn(i, m)
	{
		scanf(" %c%d", &ch[i], &zn[i]);
		div[ch[i]].pb(zn[i]);
		k[ch[i]] = k[ch[i]] * zn[i] / gcd(k[ch[i]], zn[i]);
		used[ch[i]] = 1;
	}

	K = 0;
	now.clear();
	rec(0);
	m = value[0].size();

	seta(a, 0);
	forn(i, K)
		forn(j, m)
		{
			vector <pair <char, int> > tmp = value[i];
			tmp[j].sc= (tmp[j].sc+ 1) % k[tmp[j].fs];
			a[i][num[tmp]]++;
		}

	seta(res, 0);
	forn(i, K)
		res[i][i] = 1;
	while (n > 0)
	{
		if (n & 1)
		{
			seta(q, 0);
			forn(i, K)
				forn(j, K)
					forn(f, K)
						q[i][j] = (q[i][j] + res[i][f] * a[f][j]) % P;
			forn(i, K)
				forn(j, K)
					res[i][j] = q[i][j];
		}
		seta(q, 0);
		forn(i, K)
			forn(j, K)
				forn(f, K)
					q[i][j] = (q[i][j] + a[i][f] * a[f][j]) % P;
		forn(i, K)
			forn(j, K)
				a[i][j] = q[i][j];
		n >>= 1;
	}

	int ans = 0;
	forn(i, K)
	{
		int ok = 1;
		forn(j, m)
		{
			int tmp = 0;
			char c = value[0][j].fs;
			forn(f, div[c].size())
				if (value[i][j].sc % div[c][f] == 0) tmp = 1;
			ok &= tmp;
		}
		ans = (ans + ok * res[0][i]) % P;
	}
	cout << ans << endl;

	return 0;
}

/**
 * code generated by JHelper
 * More info: https://github.com/AlexeyDmitriev/JHelper
 * @author Ankur Dua
 */

#include <iostream>
#include <fstream>

#include <bits/stdc++.h>

using namespace std;

using ll = long long;
ll mod=1000000007;
ll *fact, *ifact;

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

ll modExp(ll base, ll exp, ll mod=::mod){
    ll ans=1;
    while(exp) {
        if (exp & 1) {
            (ans *= base) %= mod;
        }
        (base *= base) %= mod;
        exp>>=1;
    }
    return ans;
}
ll modInv(ll x, ll mod=::mod){
    return modExp(x,mod-2,mod);
}
void modFact(ll n, ll mod=::mod){
    ifact=new ll[n+1];
    fact=new ll[n+1];
    fact[0]=fact[1]=1;
    for(int i=2;i<=n;i++){
        fact[i]=(i*fact[i-1])%mod;
    }
    ifact[n]=modInv(fact[n], mod);
    for(int i=n-1;i>=0;i--){
        ifact[i]=((i+1)*ifact[i+1])%mod;
    }
}
ll ncr(ll n, ll r, ll mod=::mod){
    if(n<r || r<0)
        return 0;
    ll ans=fact[n];
    ans*=ifact[r];
    ans%=mod;
    ans*=ifact[n-r];
    ans%=mod;
    return ans;
}
ll npr(ll n, ll r, ll mod=::mod){
    if(n<r || r<0)
        return 0;
    ll ans=fact[n];
    ans*=ifact[n-r];
    return ans%mod;
}

template <typename T>
void coordinateCompress(vector<T> &v, T start = 1){
    vector<T> cpy = v;
    sort(cpy.begin(), cpy.end());
    map<T,T> mp;
    for(T x:cpy){
        mp[x]=start++;
    }
    for(T &x:v){
        x=mp[x];
    }
}
template<typename T1, typename T2>
istream& operator >>(istream& cin, pair<T1, T2> &p){
	cin>>p.first>>p.second;
	return cin;
}
using namespace std;

vector<vector<ll>> operator *(vector<vector<ll>> &a, vector<vector<ll>> &b){
	int n=a.size();
	vector<vector<ll>> ans(n, vector<ll>(n));
	for(int i=0;i<n;i++){
		for(int j=0;j<n;j++){
			ll &val=ans[i][j];
			for(int k=0;k<n;k++){
				val+=a[i][k]*b[k][j];
			}
			val%=12345;
		}
	}
	return ans;
}
class DCrimeManagement {
public:

	void solve(std::istream& cin, std::ostream& cout) {
		ll n, c;
		cin>>n>>c;
		if(n==0){
			cout<<1<<endl;
			return;
		}
		if(c==0){
			cout<<0<<endl;
			return;
		}
		vector<vector<int>> v(26);
		for(int i=0;i<c;i++){
			char c;
			int x;
			cin>>c>>x;
			v[c-'A'].push_back(x);
		}
		v.resize(remove_if(v.begin(), v.end(), [](vector<int> x){return x.empty();})-v.begin());
		vector<int> product(v.size());
		for(int i=0;i<v.size();i++){
			product[i]=1;
			for(int x:v[i])
				product[i]=(product[i]*x)/__gcd(product[i], x);
		}
		int m=product.size();
		vector<vector<int>> ways;
		ways.push_back(vector<int>());
		for(int x:product){
			vector<vector<int>> ways2;
			for(int i=0;i<x;i++){
				for(auto way:ways){
					if(!i) i=i+x;
					way.push_back(i);
					ways2.push_back(way);
				}
			}
			swap(ways, ways2);
		}
		int sz=ways.size();
		map<vector<int>, int> mp;
		for(int i=0;i<ways.size();i++)
			mp[ways[i]]=i;
		vector<vector<ll>> mat(sz, vector<ll>(sz));
		for(int i=0;i<sz;i++){
			for(int j=0;j<m;j++){
				vector<int> way=ways[i];
				int nextWay=mp[way];
				mat[i][nextWay]++;
			}
		}
		vector<vector<ll>> ans(sz, vector<ll>(sz));
		for(int i=0;i<sz;i++)ans[i][i]=1;
		while(n){
			if(n&1){
				ans=ans*mat;
			}
			n>>=1;
			mat=mat*mat;
		}
		ll sum=0;
		for(int i=0;i<sz;i++){
			bool valid=true;
			vector<int> way=ways[i];
			for(int j=0;j<m;j++){
				bool flag=false;
				for(int x:v[j])
					if(way[j]%x==0)
						flag=true;
				valid=valid&&flag;
			}
			if(valid)
				sum+=ans[i][0];
		}
		cout<<(sum%12345)<<endl;
	}
};

int main() {
	DCrimeManagement solver;
	std::ios::sync_with_stdio(false);
	std::cin.tie(NULL);
	std::cout.tie(NULL);
	std::istream& in(std::cin);
	std::ostream& out(std::cout);
	solver.solve(in, out);
	return 0;
}