矩阵快速幂
写出dp方程
状态就是所有模数的余数值的所有情况
#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;
}