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

      

  • 相关阅读:
    LeetCode 1245. Tree Diameter
    LeetCode 1152. Analyze User Website Visit Pattern
    LeetCode 1223. Dice Roll Simulation
    LeetCode 912. Sort an Array
    LeetCode 993. Cousins in Binary Tree
    LeetCode 1047. Remove All Adjacent Duplicates In String
    LeetCode 390. Elimination Game
    LeetCode 1209. Remove All Adjacent Duplicates in String II
    LeetCode 797. All Paths From Source to Target
    LeetCode 1029. Two City Scheduling
  • 原文地址:https://www.cnblogs.com/clrs97/p/8542971.html
Copyright © 2011-2022 走看看