#include <vector>
#include <list>
#include <map>
#include <set>
#include <deque>
#include <stack>
#include <queue>
#include <algorithm>
#include <sstream>
#include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <cstdlib>
#include <ctime>
#include <memory.h>

#define MP make_pair
#define VI vector<int>
#define PI 3.14159265358979
#define LL long long
#define PII pair<int,int>
#define Mod 12345
using namespace std;

LL C, N;
int MaxN;
struct Mat
{
	LL a[130][130];
};

void Mul( const Mat &a, const Mat &b, Mat &c, int size )
{
	for( int i = 0; i < size; ++ i )
	{
		for( int j = 0; j < size; ++ j )
		{
			c.a[i][j] = 0;
			for( int k = 0; k < size; ++ k )
				c.a[i][j] += a.a[i][k] * b.a[k][j];
			c.a[i][j] %= Mod;
		}
	}
}

void Pow( const Mat &a, Mat &b, LL n, int size )
{
	int t[80], index = 0;
	while( n )
		t[index ++] = n & 1, n >>= 1;
	Mat m;
	memset( m.a, 0, sizeof( m.a ) );
	for( int i = 0; i < size; ++ i )
		m.a[i][i] = 1;
	Mat ret = m;
	for( int i = index - 1; i >= 0; -- i )
	{
		Mul( m, m, ret, size );
		memcpy( m.a, ret.a, sizeof( m.a ) );
		if( t[i] )
		{
			Mul( m, a, ret, size );
			memcpy( m.a, ret.a, sizeof( m.a ) );
		}
	}
	b = ret;
}

int gcd( int x, int y )
{
	while( x && y )
	{
		if( x >= y ) x %= y;
		else y %= x;
	}
	return x + y;
}

int main()
{
#if _MSC_VER == 1500
	freopen( "in.txt", "r", stdin );
#endif
	cin >> N >> C;
	VI itv[26];
	int f[26] = {};
	for( int i = 0; i < C; ++ i )
	{
		char x; int t;
		cin >> x >> t;
		itv[x - 'A'].push_back( t );
	}
	MaxN = 1;
	for( int i = 0; i < 26; ++ i )
	{
		if( itv[i].size() == 0 ) continue;
		unique( itv[i].begin(), itv[i].end() );
		f[i] = 1;
		for( int j = 0; j < itv[i].size(); ++ j )
			f[i] = f[i] / gcd( f[i], itv[i][j] ) * itv[i][j];
		MaxN *= f[i];
	}
	Mat init, ret;
	memset( init.a, 0, sizeof( init.a ) );
	int t[26] = {};
	for( int i = 0; i < MaxN; ++ i )
	{
		int cur = i;
		for( int j = 0; j < 26; ++ j )
		{
			if( f[j] == 0 ) continue;
			t[j] = cur % f[j];
			cur /= f[j];
		}
		for( int j = 0; j < 26; ++ j )
		{
			if( f[j] == 0 ) continue;
			t[j] ++;
			if( t[j] >= f[j] ) t[j] -= f[j];
			int val = 0;
			for( int k = 25; k >= 0; -- k )
			{
				if( f[k] == 0 ) continue;
				val = val * f[k] + t[k];
			}
			init.a[i][val] ++;
			t[j] --;
			if( t[j] < 0 ) t[j] = f[j] - 1;
		}
	}
	Pow( init, ret, N, MaxN );
	int ans = 0;
	for( int i = 0; i < MaxN; ++ i )
	{
		bool ac = 1;
		int cur = i;
		for( int j = 0; j < 26; ++ j )
		{
			if( f[j] == 0 ) continue;
			t[j] = cur % f[j];
			cur /= f[j];
		}
		for( int j = 0; j < 26; ++ j )
		{
			if( f[j] == 0 ) continue;
			int flag = 0;
			for( int k = 0; k < itv[j].size(); ++ k )
				if( t[j] % itv[j][k] == 0 )
					flag = 1;
			if( flag == 0 )
			{
				ac = 0;
				break;
			}
		}
		if( ac )
			ans = ( ans + ret.a[i][0] ) % Mod;
	}
	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 <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 <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;
}

#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 <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 <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);
}

#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;
}

//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<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<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;
}

#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<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;
}

#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<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;
}

/*
 * 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;
}

/**
 * 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 <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 <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 <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;
}

// 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 <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<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);
}

#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;
}

// 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<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<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);
}

#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;

}

#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<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<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>
#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;
}

#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 <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 <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;
}

//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 <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 <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 <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 <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<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 <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;
}

/*
「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<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 <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 <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

#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

/*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 <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 <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 <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;
}

#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;
}

#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;
}

#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 <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;
}

#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<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 <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 <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<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);
}

//#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<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);
}

//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 <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);
}

#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;
}

#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 <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 <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;
}

/*
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;
}

//#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;
}

#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 <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 <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<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 <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;
}

#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 <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>
//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 <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;
}