zoukankan      html  css  js  c++  java
  • CF 506E

    Description

     

    Input

    Output

     

    Sample Input

    输入1:
    add
    2
    输入2:
    xzx
    0

    Sample Output

    输出1:
    28

    输出2:
    1
     

    Data Constraint

     

    首先有一个40分dp的解法, 设f[i][l][r]表示回文串已填了i位,给出串从左边匹配到第l位,右边匹配到第r位的方案数,如果能匹配则强制匹配,这样可以去重。

    但对于100%的数据N非常大,自然想到用矩阵乘法快速幂优化。

    按照dp的转移我们可以建出一张图。每个点D(l,r)表示原串分别匹配到(l,r)位,那么即可根据dp的转移连边

    Eg.

    对于add连边如下

    这样有S^2级别的点,在图上对于每条路径用矩乘优化依然会超时。

    然而我们发现一条路径走就是在每个节点分别的不断自环,不记先后顺序,所以如果两条路径上24环的数量一致,那么它们25环和26环的数量也会一致,对答案的贡献也是一致的,可以一起计算。这样我们可以先用一个dp预处理出24环数为i的路径有多少条。

    然而如果对于每条路径都矩乘一次,仍然会超时。我们发现对于两条24环数不同的路径,其中一条可能为另一条的一部分,所以不需要重复计算。

    据此我们可以构一张大图,左边都是24点,右边都是25点,每个25点连一个26点,对大图作一次矩乘,然后每条路径只是起点和终点不同而已(例如对于经过1个24,2个25的路径即为3号到8号点的路径)

    正常来说这样就能过了,但本题中我们还需要优化矩乘,合理标号我们可以发现,只有编号小的到编号大的点有边,那么这样就可以限制j,k的范围,我们还可以把k放在第二维,减少寻址的耗时。

    End.

    #include<cstdio>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    
    using namespace std;
    
    
    struct Matrix{
        int a[402][402];
    };
    
    Matrix ans,d,g,anso,anst;
    int mo=10007;
    char s[221];
    int i,L,n,N,Ans,tot;
    int dp[211][2];
    int f[211][211][211];
    
    Matrix operator *(Matrix a,Matrix b)
    {
        int i,j,k,Tmp;
        Matrix c;
        for(i=1;i<=tot;i++)
            for(j=1;j<=tot;j++)c.a[i][j]=0;
        for(i=1;i<=tot;i++)
            for(k=i;k<=tot;k++)if(a.a[i][k]){
                Tmp=a.a[i][k];
                for(j=k;j<=tot;j++)c.a[i][j]=(c.a[i][j]+Tmp*b.a[k][j])%mo;
            }
        return c;
    }
    
    void update(int i,int nl,int nr,int l,int r)
    {
        if(nl+1>=nr){
            if(N%2==0)dp[i][0]=(dp[i][0]+f[i][l][r])%mo;
            else{
                if(nl+1==nr)dp[i][0]=(dp[i][0]+f[i][l][r])%mo;
                else dp[i][1]=(dp[i][1]+f[i][l][r])%mo;
            }
        }
        else{
            if(s[nl+1]==s[nr-1])f[i][nl][nr]=(f[i][nl][nr]+f[i][l][r])%mo;
            else f[i+1][nl][nr]=(f[i+1][nl][nr]+f[i][l][r])%mo;
        }
    }
    
    void prepare()
    {
        int i,j,l,r,nl,nr;
        if(s[1]==s[L])f[0][0][L+1]=1;
        else f[1][0][L+1]=1;
        for(i=0;i<=L;i++)
            for(l=0;l<=L;l++)
                for(r=L+1;r>=l;r--)if(f[i][l][r]){
                    if(l+1<=r-1){
                        if(s[l+1]==s[r-1])update(i,l+1,r-1,l,r);
                        else{
                            update(i,l+1,r,l,r);
                            update(i,l,r-1,l,r);
                        }
                    }
                }
    }
    
    void build()
    {
        int i;
        for(i=1;i<=L;i++)d.a[i][i]=24,d.a[i][i+1]=1;
        for(i=1;i<=(L+1)/2;i++){
            tot=L+i;
            if(i!=(L+1)/2)d.a[tot][tot+1]=1;
            d.a[tot][tot]=25;
            d.a[tot][tot+(L+1)/2]=1;
            d.a[tot+(L+1)/2][tot+(L+1)/2]=26;
        }
        tot+=(L+1)/2;
    }
    
    void mi(int x)
    {
        while(x){
            if(x%2==1)ans=ans*d;
            x/=2;
            d=d*d;
        }
    }
    
    void work()
    {
        int i,j;
        for(i=1;i<=tot;i++)ans.a[i][i]=1;
        for(i=1;i<=tot;i++)
            for(j=1;j<=tot;j++)g.a[i][j]=d.a[i][j];
        if(N%2==1){
            mi(N/2);
            for(i=1;i<=tot;i++)
                for(j=1;j<=tot;j++){
                    d.a[i][j]=g.a[i][j];
                    anso.a[i][j]=ans.a[i][j];
                }
            mi(1);
            for(i=1;i<=tot;i++)
                for(j=1;j<=tot;j++){
                    anst.a[i][j]=ans.a[i][j];
                    ans.a[i][j]=anso.a[i][j];
                    d.a[i][j]=g.a[i][j];
                }
            for(i=1;i<=(L+1)/2;i++)d.a[L+i][L+i+(L+1)/2]=0;
            mi(1);
        }
        else mi(N/2);
    }
    
    void calc()
    {
        int i,ts,tg;
        for(i=0;i<=L;i++){
            dp[i][0]=dp[i][0]%mo;
            dp[i][1]=dp[i][1]%mo;
            ts=i;
            if((L-ts)%2==1)tg=(L+1-ts)/2;
            else tg=(L-ts)/2;
            Ans=(Ans+dp[i][0]*ans.a[L-ts+1][L+tg+(L+1)/2])%mo;
            Ans=(Ans+dp[i][1]*anst.a[L-ts+1][L+tg+(L+1)/2])%mo;
        }
    }
    
    int main()
    {
        scanf("%s",s+1);
        scanf("%d",&n);
        L=strlen(s+1);
        N=n+L;
        prepare();
        build();
        work();
        calc();
        printf("%d
    ",Ans);
    }
  • 相关阅读:
    顺序 | order (Flexible Box Layout)
    顶部边距 | margin-top (Basic Box Model)
    面具重复 | mask-repeat (Masking)
    面具类型 | mask-type (Masking)
    面具模型 | mask-mode (Masking)
    面具大小 | mask-size (Masking)
    面具图像 | mask-image (Masking)
    mycat 只分库,不分表,并且主从读写分离范例
    《风控模型—WOE与IV指标的深入理解应用》
    《风控模型—群体稳定性指标(PSI)深入理解应用》
  • 原文地址:https://www.cnblogs.com/applejxt/p/4433318.html
Copyright © 2011-2022 走看看