zoukankan      html  css  js  c++  java
  • 2019.01.19-2018年6月NEYC集训sequence

    题目描述:

    茉优最近研究发现,一个人的想愿能力可以认为是字符串S的一个子串S[l,r],而连接值可以认为是这个子串的本质不同子序列个数。现在她想验证她的结论是否正确,于是她给了你Q个询问,希望你帮她来计算,注意空串也是子序列。

    因为茉优已经有一个答案了,所以你只要输出ZQ的值检验即可。

    思路:

    考虑对于取以字符i为结尾的转移矩阵,是除了单位矩阵外,第一列为都为1,恰好表示除了以i为结尾的情况其他情况都*2.

    于是构建出每个字母的转移矩阵,是一个53*53的矩阵,叫它C[i]。

    对于每一个询问,答案其实是前Ar个矩阵的乘积,乘上前Al-1个矩阵的逆。

    但是由于矩阵不满足交换律,所以我们呢要做这样的预处理。

    Ar=Ar-1*Cs[a[r]]

    B表示逆矩阵。

    Bl=Cs[a[l]]*Bl-1

    Ans=一个1*m的矩阵(只有第一位为0)*Bl*Ar

    仔细分析可以发现关于B矩阵我们只需要知道第一行每一位数的数值,

    A矩阵我们只需要知道每一列的和。

    并且由于每个字母转移矩阵的特殊性,计算过程中结果通常只和一行或一列相关,于是每次维护或一列即可,转移时O(53)

    总效率就是O(n*53).

    以下代码:

    #include<bits/stdc++.h>
    #define il inline
    #define _(d) while(d(isdigit(ch=getchar())))
    using namespace std;
    const int N=1e6+5,p=998244353;
    char s[N];
    int Q,a0,b0,B,q,R,n,tag[55],ans;
    struct node{
        int l[55];
    }a[N],b[N],c[55];
    il int read(){
        int x,f=1;char ch;
        _(!)ch=='-'?f=-1:f;x=ch^48;
        _()x=(x<<1)+(x<<3)+(ch^48);
        return f*x;
    }
    il int C(char a){
        if(a<='Z')return a-'A'+1;
        return a-'a'+27;
    }
    il int mu(int x,int y){
        if(x+y>=p)return x+y-p;
        return x+y;
    }
    int main()
    {
        scanf(" %s",s+1);n=strlen(s+1);
        for(int i=0;i<53;i++)c[i].l[i]=a[0].l[i]=1;
        for(int i=1;i<=n;i++){
            int k=C(s[i]);
            for(int tmp,j=0;j<53;j++){
                tmp=c[j].l[k];c[j].l[k]=a[i-1].l[j];
                a[i].l[j]=mu(mu(a[i-1].l[j],a[i-1].l[j]),p-tmp);
            }
        }
        for(int i=0;i<53;i++){
            for(int j=0;j<53;j++){
                c[i].l[j]=0;
            }
            c[i].l[i]=1;
        }
        b[0].l[0]=1;
        for(int i=1;i<=n;i++){
            int k=C(s[i]);
            for(int tmp,j=0;j<53;j++){
                tmp=mu(c[k].l[j],p-tag[j]);c[k].l[j]=mu(c[k].l[j],tmp);
                tag[j]=mu(tag[j],tmp);b[i].l[j]=mu(c[0].l[j],p-tag[j]);
            }
        }
        Q=read();a0=read();b0=read();B=read();q=read();R=read();
        while(Q--){
            int a1,b1,l,r;
            a1=mu(mu(1ll*B*a0%p,1ll*q*b0%p),mu(ans,R));
            b1=mu(mu(1ll*B*b0%p,1ll*q*a0%p),mu(ans,R));
            a0=a1;b0=b1;l=a0%n+1;r=b0%n+1;
            if(l>r)swap(l,r);
            ans=0;
            for(int i=0;i<53;i++){
                ans=mu(ans,1ll*a[r].l[i]*b[l-1].l[i]%p);
            }
        }
        printf("%d
    ",ans);
        return 0;
    }
    View Code
  • 相关阅读:
    第五周课后作业
    第五周读书笔记
    PB16120853+JL17110067
    第一次个人作业报告
    《编程匠艺》读书笔记----第四周
    软工第一次个人作业博客(一)
    软工第一次个人作业博客(二)
    《程序员修炼之道》读书笔记(二)--第三周
    关于在aspx前台使用后台变量的问题
    sql语句优化SQL Server
  • 原文地址:https://www.cnblogs.com/Jessie-/p/10291652.html
Copyright © 2011-2022 走看看