根據Polya定理:
\[ans=\frac{\sum_{d|n}\varphi(d)cal(\frac{n}{d})}{n}\]
其中$cal(n)$表示長度為$n$的無限迴圈後包含$S$的串的數量。
對於$cal(n)$的計算,考慮用總方案數$2^n$減去單次迴圈內不包含$S$的方案數。
列舉進入迴圈時與$S$的KMP指標$k$,然後設$f[i][j]$表示考慮前$i$個位置,KMP指標為$j$的方案數,最終結果為$f[n][k]$。
轉移可以用矩陣$G$表示,預處理出$G$的$2^0,2^1,...,2^{\log n}$次方,那麼每次計算$cal(n)$只需要進行$O(k\log n)$次$O(k^2)$的矩陣乘向量。
總時間複雜度$O(d(n)k^3\log n)$。
#include<cstdio> #define rep(i) for(int i=0;i<m;i++) const int N=35,P=1000000007; int n,m,i,j,k,nxt[N],g[N][2],e[N][N][N],c[N][N],f[N],h[N],ans;char a[N]; inline void mul(int a[][N],int f[][N]){ rep(i)rep(j)c[i][j]=0; rep(i)rep(j)if(a[i][j])rep(k)if(a[j][k])c[i][k]=(1LL*a[i][j]*a[j][k]+c[i][k])%P; rep(i)rep(j)f[i][j]=c[i][j]; } inline void mulv(int a[][N]){ rep(i){ h[i]=0; rep(j)if(f[j]&&a[i][j])h[i]=(1LL*f[j]*a[i][j]+h[i])%P; } rep(i)f[i]=h[i]; } inline int phi(int n){ int t=1; for(int i=2;i<=n/i;i++)if(n%i==0){ t*=i-1,n/=i; while(n%i==0)t*=i,n/=i; } if(n>1)t*=n-1; return t; } inline int po(int a,int b){int t=1;for(;b;b>>=1,a=1LL*a*a%P)if(b&1)t=1LL*t*a%P;return t;} inline int cal(int n){ int t=0; for(int i=0;i<m;i++){ rep(j)f[j]=i==j; for(int j=0;(1LL<<j)<=n;j++)if(n>>j&1)mulv(e[j]); t=(t+f[i])%P; } return(po(2,n)-t+P)%P; } int main(){ scanf("%d%d%s",&n,&m,a+1); for(i=1;i<=m;i++)a[i]=a[i]=='R'; for(i=2;i<=m;nxt[i++]=j){ while(j&&a[j+1]!=a[i])j=nxt[j]; if(a[j+1]==a[i])j++; } rep(i)for(j=0;j<2;j++){ for(k=i;k&&a[k+1]!=j;k=nxt[k]); if(a[k+1]==j)k++; g[i][j]=k; } rep(i)for(j=0;j<2;j++)e[0][g[i][j]][i]++; for(i=1;(1LL<<i)<=n;i++)mul(e[i-1],e[i]); for(i=1;i<=n/i;i++)if(n%i==0){ ans=(1LL*phi(i)*cal(n/i)+ans)%P; if(i*i!=n)ans=(1LL*phi(n/i)*cal(i)+ans)%P; } ans=1LL*ans*po(n,P-2)%P; return printf("%d",ans),0; }