Given a string a (len < = 20) composed of numbers, let you choose a string x with a length of n(n is given). A legal string x is defined as that there is no segment of string X that is exactly the same as a. find the number of different legal strings L
At the first sight, there is no idea.... after a glance, KMP optimizes DP, and then matrix optimizes DP
The idea is not difficult. First, use KMP to find the next array of the original string, and then use next to transfer
The definition f[i][j] is that the current X string has been matched to the i-th bit, and has been matched to the j-th bit of string A
Fill in A number c in the j+1 bit of X string every time, then the longest x string can match the position of A string
That is, jump forward from the j+1 bit until a position a[k]==a[j] or k==0 is not matched
int k=i+1; for(k=i+1;k>0&&a[k]!=c;k=nxt[k]) ; pw.mp[k][i]++;
This is a continuous process. The above is the core code of building matrix (the original code is too ugly, I changed it)
As for why we should jump like this, it's a process similar to "greed", but it's not that we take the initiative to be greedy
Because we need to make sure that every time we move it, it's the right place
Then it is found that n < = 1e9 is a little large, and matrix multiplication can be optimized
#include <map> #include <cmath> #include <cstdio> #include <cstring> #include <algorithm> #define ll long long #define N 23 #define ui unsigned int #define inf 0x3f3f3f3f using namespace std; //re int n,len; ui mod; char str[N]; int a[N],nxt[N]; struct mtx{ ui mp[N][N]; friend mtx operator *(const mtx &s1,const mtx &s2) { mtx ret;memset(&ret,0,sizeof(ret)); for(int i=0;i<len;i++) for(int j=0;j<len;j++) for(int k=0;k<len;k++) (ret.mp[i][j]+=(s1.mp[i][k]*s2.mp[k][j])%mod)%=mod; return ret; } mtx qpow(mtx &ans,mtx &x,int y) { while(y){ if(y&1) ans=x*ans; x=x*x;y>>=1; } } }M; void get_kmp() { int i=1,j=0; nxt[1]=0; while(i<=len) if(j==0||a[i]==a[j]) i++,j++,nxt[i]=j; else j=nxt[j]; } int main() { scanf("%d%d%u",&n,&len,&mod); scanf("%s",str+1); for(int i=1;i<=len;i++) a[i]=str[i]-'0'; get_kmp(); mtx pw;memset(&pw,0,sizeof(pw)); for(int i=0;i<len;i++) for(int c=0;c<=9;c++) { if(i==len-1&&a[len]==c) continue; int k=i+1; for(k=i+1;k>0&&a[k]!=c;k=nxt[k]); pw.mp[k][i]++; } mtx ret;memset(&ret,0,sizeof(ret)); ret.mp[0][0]=1; M.qpow(ret,pw,n); ui ans=0; for(int i=0;i<len;i++) (ans+=ret.mp[i][0])%=mod; printf("%u\n",ans); return 0; }