• 【AC自动机】【矩阵乘法】【等比数列】hdu2243 考研路茫茫——单词情结


    题解:http://blog.csdn.net/xingyeyongheng/article/details/10005923

    这里采用了二分法求等比数列前n项和。

    等比数列前n项和也可以用矩乘快速幂来求[a 1]    [Sn]    =    [Sn+1]

                        [0 1]    [a  ]          [   a   ]

    #include<cstdio>
    #include<cstring>
    #include<vector>
    #include<queue>
    #include<iostream>
    using namespace std;
    typedef unsigned long long ull;
    typedef vector<ull> vec;
    typedef vector<vec> mat;
    typedef pair<mat,mat> Point2;
    typedef pair<ull,ull> Point;
    int N;
    mat I;
    mat operator * (const mat &a,const mat &b)
    {
        mat c(N,vec(N));
        for(int i=0;i<N;++i)
          for(int j=0;j<N;++j)
            for(int k=0;k<N;++k)
              c[i][j]=c[i][j]+a[i][k]*b[k][j];
        return c;
    }
    mat operator - (const mat &a,const mat &b)
    {
        mat c(N,vec(N));
        for(int i=0;i<N;++i)
          for(int j=0;j<N;++j)
            c[i][j]=a[i][j]-b[i][j];
        return c;
    }
    mat operator + (const mat &a,const mat &b)
    {
        mat c(N,vec(N));
        for(int i=0;i<N;++i)
          for(int j=0;j<N;++j)
            c[i][j]=a[i][j]+b[i][j];
        return c;
    }
    Point sum_a_n(ull a,ull n)
    {
    	if(n==0)
    	  return Point(1,1);
    	Point t=sum_a_n(a,n>>1);
    	if(n&1)
    	  return Point(t.first*t.first*a,t.second*(t.first*a+1));
    	else
    	  return Point(t.first*t.first,(t.second-t.first)*(t.first*a+1)+t.first);
    }
    Point2 sum_A_n(mat a,ull n)
    {
    	if(n==0)
    	  return Point2(I,I);
    	Point2 t=sum_A_n(a,n>>1);
    	if(n&1)
    	  return Point2(t.first*t.first*a,t.second*(t.first*a+I));
    	else
    	  return Point2(t.first*t.first,(t.second-t.first)*(t.first*a+I)+t.first);
    }
    queue<int>q;
    int child[40][26],fail[40],size=1;
    bool word[40];
    void Insert(char S[])
    {
        int len=strlen(S);
        int now=0;
        for(int i=0;i<len;++i)
          {
            if(!child[now][S[i]-'a'])
              child[now][S[i]-'a']=size++;
            now=child[now][S[i]-'a'];
          }
        word[now]=1;
    }
    void build()
    {
        fail[0]=-1;
        q.push(0);
        while(!q.empty())
          {
            int U=q.front(); q.pop();
            for(int i=0;i<26;++i)
              if(child[U][i])
                {
                  int V=fail[U];
                  while(V!=-1)
                    {
                      if(child[V][i])
                        {
                          fail[child[U][i]]=child[V][i];
                          break;
                        }
                      V=fail[V];
                    }
                  if(V==-1)
                    fail[child[U][i]]=0;
                  if(word[fail[child[U][i]]])
                    word[child[U][i]]=1;
                  q.push(child[U][i]);
                }
              else if(U)
                child[U][i]=child[fail[U]][i];
          }
    }
    int n,ma2[40];
    ull m;
    void Init()
    {
    	memset(child,0,sizeof(child));
    	memset(fail,0,sizeof(fail));
    	memset(word,0,sizeof(word));
    	N=0;
    	size=1;
    }
    int main()
    {
    	//freopen("hdu2243.in","r",stdin);
        char s[8];
        while(cin>>n>>m){
        Init();
        for(int i=1;i<=n;++i)
          {
            scanf("%s",s);
            Insert(s);
          }
        build();
        for(int i=0;i<size;++i)
          if(!word[i])
            ma2[i]=N++;
        I.assign(N,vec(N));
        for(int i=0;i<N;++i)
          I[i][i]=1;
        mat A(N,vec(N));
        for(int i=0;i<size;++i)
          for(int j=0;j<26;++j) if((!word[i]) && (!word[child[i][j]]))
            ++A[ma2[i]][ma2[child[i][j]]];
        A=sum_A_n(A,m).second-I;
        ull ans=sum_a_n(26,m).second-1;
        for(int i=0;i<N;++i)
          ans=ans-A[0][i];
        cout<<ans<<endl;
    	}
        return 0;
    }
  • 相关阅读:
    BZOJ3512 DZY Loves Math IV
    HDU5608 function
    数论
    动态点分治
    tarjan
    插头DP
    斯坦纳树
    css中的display(显示)和visibility(可见性)
    简单的数据整理, 递归算法
    java链接数据库构建sql语句的时候容易记混的地方
  • 原文地址:https://www.cnblogs.com/autsky-jadek/p/6504500.html
Copyright © 2020-2023  润新知