zoukankan      html  css  js  c++  java
  • BZOJ3457 : Ring

    根据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(klog n)$次$O(k^2)$的矩阵乘向量。

    总时间复杂度$O(d(n)k^3log 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;
    }
    

      

  • 相关阅读:
    JAVA学习25天
    Java学习第24天
    Java学习第23天
    Java学习22天
    第3周
    Java21
    day23作业
    day23
    Typecho使用技巧
    搭建Typecho博客
  • 原文地址:https://www.cnblogs.com/clrs97/p/8542971.html
Copyright © 2011-2022 走看看