2024寒假自主提升日记

2.7

闲话

做题纪要

SP26368 PWRANDMOD - Power and Mod

  • 龟速乘板子。

    点击查看代码
    #define ll __int128_t 
    ll read()
    {
        ll x=0,f=1;
        char c=getchar();
        while(c>'9'||c<'0')
        {
            if(c=='-')
            {
                f=-1;
            }
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    void write(ll x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9)
        {
            write(x/10);
        }
        putchar((x%10)+'0');
    }
    ll smul(ll a,ll b,ll p)
    {
        ll ans=0;
        while(b>0)
        {
            if(b&1)
            {
                ans=(ans+a)%p;
            }
            b>>=1;
            a=(a+a)%p;
        }
        return ans;
    }
    ll qpow(ll a,ll b,ll p)
    {
        ll ans=1;
        while(b>0)
        {
            if(b&1)
            {
                ans=smul(ans,a,p);
            }
            b>>=1;
            a=smul(a,a,p);
        }
        return ans;
    }
    int main()
    {
        ll t,a,b,p,i;
        t=read();
        for(i=1;i<=t;i++)
        {
            a=read();
            b=read();
            p=read();
            write(qpow(a,b,p));
            cout<<endl;
        }
        return 0;
    }
    

SP277 CTGAME - City Game

2.8

闲话

做题纪要

2.9

闲话

做题纪要

luogu P2440 木材加工

  • 简单的二分答案,为什么我考场上没有看出来醉了。

  • 注意可能会出现除数为 \(0\) 的情况,即 \(mid=\left\lfloor\dfrac{0+1}{2}\right\rfloor=0\) 时。将二分左端点初始化为 \(1\) 或对 \(mid=0\) 进行特判即可。

    点击查看代码
    int a[1000001];
    bool check(int mid,int n,int m)
    {
        int sum=0,i;
        for(i=1;i<=n;i++)
        {
            sum+=a[i]/mid;
        }
        return sum>=m;
    }
    int main()
    {
        int n,m,ans,l=1,r=0,mid,i;
        cin>>n>>m;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
            r=max(r,a[i]);
        }
        while(l<=r)
        {
            mid=(l+r)/2;
            if(check(mid,n,m)==true)
            {
                ans=mid;
                l=mid+1;
            }
            else
            {
                r=mid-1;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

CF1331G Lingua Romana

  • 愚人节的题,建议去看官方题解要简化题意。

    点击查看代码
    double a[1001];
    int main()
    {
        int i;
        for(i=1;i<=11;i++)
        {
            cin>>a[i];
        }
        for(i=11;i>=1;i--)
        {
            if(a[i]<5)
            {
                printf("f(%.0lf) = %.2lf\n",a[i],5*a[i]*a[i]*a[i]+sqrt(abs(a[i])));
            }
            else
            {
                printf("f(%.0lf) = MAGNA NIMIS!\n",a[i]);
            }
        }
        return 0;
    }
    

2.10

闲话

做题纪要

HZOJ 863. 金牌

luogu P8670 [蓝桥杯 2018 国 B] 矩阵求和

2.11

闲话

做题纪要

luogu P4783 【模板】矩阵求逆

  • 矩阵求逆板子。

  • 若对于矩阵 \(A\) 存在一个矩阵 \(A^{-1}\) 使得 \(A \times A^{-1}=I\)\(A^{-1} \times A =I\) ,其中 \(I\) 为单位矩阵 \(I= \begin{bmatrix} 1 & 0 & \cdots & 0 \\ 0 & 1 & \cdots & 0 \\ \vdots & \vdots & \ddots & \vdots \\ 0 & 0 & \cdots & 1 \end{bmatrix}\) ,则称 \(A\) 是可逆的且逆是唯一的, \(A^{-1}\)\(A\) 的逆矩阵。

  • 已知 \(\begin{bmatrix} A & I \end{bmatrix}\) ,考虑将其变成 \(\begin{bmatrix} I & A^{-1} \end{bmatrix}\) 。第一种方法是 \(\begin{bmatrix} A & I \end{bmatrix} \times A^{-1}= \begin{bmatrix} I & A^{-1} \end{bmatrix}\) ;另一种方法是对 \(A\) 进行高斯消元,使其变成系数为 \(1\) 的对角矩阵,变成 \(\begin{bmatrix} I & A^{-1} \end{bmatrix}\)

    点击查看代码
    ll a[1001][1001];
    ll qpow(ll a,ll b,ll p)
    {
        ll ans=1;
        while(b>0)
        {
            if(b&1)
            {
                ans=ans*a%p;
            }
            b>>=1;
            a=a*a%p;
        }
        return ans;
    }
    int main()
    {
        ll n,inv,val=0,flag=0,i,j,k,p=1000000007;
        cin>>n;
        for(i=1;i<=n;i++)
        {
            a[i][i+n]=1;
            for(j=1;j<=n;j++)
            {
                cin>>a[i][j];
            }
        }
        for(i=1;i<=n;i++)
        {
            val=i;
            for(j=i+1;j<=n;j++)
            {
                if(abs(a[j][i])-abs(a[val][i])>0)
                {
                    val=j;
                }
            }
            for(j=1;j<=2*n;j++)
            {
                swap(a[i][j],a[val][j]);
            }
            if(a[i][i]==0)
            {
                flag=1;
                cout<<"No Solution"<<endl;
                break;
            }
            else
            {
                inv=qpow(a[i][i],p-2,p);
                for(j=1;j<=n;j++)
                {
                    if(j!=i)
                    {
                        for(k=i+1;k<=2*n;k++)
                        {
                            a[j][k]=(a[j][k]-a[i][k]*(a[j][i]*inv%p)%p+p)%p;		
                        }
                    }
                }
                for(j=1;j<=2*n;j++)
                {
                    a[i][j]=a[i][j]*inv%p;
                }
            }
        }
        if(flag==0)
        {
            for(i=1;i<=n;i++)
            {
                for(j=n+1;j<=2*n;j++)
                {
                    cout<<a[i][j]<<" ";
                }
                cout<<endl;
            }
        }
        return 0;
    }	
    

2.12

闲话

做题纪要

luogu P2044 [NOI2012] 随机数生成器

  • \(F_{n}=\begin{bmatrix} x_{n} & c \end{bmatrix}\) ,容易有 \(\begin{aligned} F_{n} &=\begin{bmatrix} x_{n} & c \end{bmatrix} \\ &=\begin{bmatrix} x_{n-1} & c \end{bmatrix} \times \begin{bmatrix} a & 0 \\ 1 & 1 \end{bmatrix} \\ &=\begin{bmatrix} x_{n-2} & c \end{bmatrix} \times \begin{bmatrix} a & 0 \\ 1 & 1 \end{bmatrix}^{2} \\ &=\begin{bmatrix} x_{n-3} & c \end{bmatrix} \times \begin{bmatrix} a & 0 \\ 1 & 1 \end{bmatrix}^{3} \\ &=\dots \\ &=\begin{bmatrix} x_{0} & c \end{bmatrix} \times \begin{bmatrix} a & 0 \\ 1 & 1 \end{bmatrix}^{n} \\ &=F_{0} \times \begin{bmatrix} a & 0 \\ 1 & 1 \end{bmatrix}^{n} \end{aligned}\)

    点击查看代码
    struct Matrix
    {
        ll ma[5][5];
        Matrix()
        {
            memset(ma,0,sizeof(ma));
        }
    }f,a;
    ll read()
    {
        ll x=0,f=1;
        char c=getchar();
        while(c>'9'||c<'0')
        {
            if(c=='-')
            {
                f=-1;
            }
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    void write(ll x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9)
        {
            write(x/10);
        }
        putchar((x%10)+'0');
    }
    Matrix mul(Matrix a,Matrix b,ll n,ll m,ll k,ll p)
    {
        Matrix c;
        for(ll i=1;i<=n;i++)
        {
            for(ll j=1;j<=k;j++)
            {
                for(ll h=1;h<=m;h++)
                {
                    c.ma[i][j]=(c.ma[i][j]+(a.ma[i][h]%p)*(b.ma[h][j]%p)%p)%p;
                }
            }
        }
        return c;
    }
    Matrix qpow(Matrix a,ll b,ll p,ll n)
    {
        Matrix ans;
        for(ll i=1;i<=n;i++)
        {
            ans.ma[i][i]=1;
        }
        while(b>0)
        {
            if(b&1)
            {
                ans=mul(ans,a,n,n,n,p);
            }
            b>>=1;
            a=mul(a,a,n,n,n,p);
        }
        return ans;
    }
    int main()
    {
        ll p,b,g,n=1,m=2,k=2;
        p=read();
        a.ma[1][1]=read();
        f.ma[1][2]=read();
        f.ma[1][1]=read();
        b=read();
        g=read();
        a.ma[1][2]=0;
        a.ma[2][1]=a.ma[2][2]=1;
        write(mul(f,qpow(a,b,p,m),n,m,k,p).ma[1][1]%g);
        return 0;
    }
    

BZOJ4128 Matrix

  • map 重载运算符即可。

  • 因常数巨大,故尽可能减少 \(BSGS\) 中多次矩阵快速幂的使用。

    点击查看代码
    ll n;
    struct Matrix
    {
        ll ma[80][80];
        Matrix()
        {
            memset(ma,0,sizeof(ma));
        }
        bool operator < (Matrix another) const
        {
            for(ll i=1;i<=n;i++)
            {
                for(ll j=1;j<=n;j++)
                {
                    if(ma[i][j]<another.ma[i][j])
                    {
                        return true;
                    }
                    if(ma[i][j]>another.ma[i][j])
                    {
                        return false;
                    }
                }
            }
            return false;
        }
    }a,b;
    Matrix mul(Matrix a,Matrix b,ll n,ll m,ll k,ll p)
    {
        Matrix c;
        for(ll i=1;i<=n;i++)
        {
            for(ll j=1;j<=k;j++)
            {
                for(ll h=1;h<=m;h++)
                {
                    c.ma[i][j]=(c.ma[i][j]+a.ma[i][h]*b.ma[h][j]%p)%p;
                }
            }
        }
        return c;
    }
    Matrix qpow(Matrix a,ll b,ll p,ll n)
    {
        Matrix ans;
        for(ll i=1;i<=n;i++)	
        {	
            ans.ma[i][i]=1;
        }
        while(b>0)
        {
            if(b&1)
            {
                ans=mul(ans,a,n,n,n,p);
            }
            b>>=1;
            a=mul(a,a,n,n,n,p);
        }
        return ans;
    }
    ll bsgs(Matrix a,Matrix b,ll p,ll n)
    {
        map<Matrix,ll>vis;
        ll k=sqrt(p)+1,i;
        Matrix sum;
        for(i=0;i<=k-1;i++)
        {
            b=(i==0)?b:mul(b,a,n,n,n,p);
            vis[b]=i;
        }
        a=qpow(a,k,p,n);
        for(i=1;i<=n;i++)
        {
            sum.ma[i][i]=1;
        }
        for(i=0;i<=k;i++)
        {
            sum=(i==0)?sum:mul(sum,a,n,n,n,p);
            if(vis.find(sum)!=vis.end())
            {
                if(i*k-vis[sum]>=0)
                {
                    return i*k-vis[sum];
                }
            }
        }
        return -1;
    }
    int main()
    {
        ll p,i,j;
        cin>>n>>p;
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                cin>>a.ma[i][j];
                a.ma[i][j]%=p;
            }
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                cin>>b.ma[i][j];
                b.ma[i][j]%=p;
            }
        }
        cout<<bsgs(a,b,p,n)<<endl;
        return 0;
    }	
    

luogu P4387 【深基15.习9】验证栈序列

  • 简单的栈模拟。

    点击查看代码
    int a[100001],b[100001];
    int main()
    {
        int q,n,r,i,j;
        cin>>q;
        for(i=1;i<=q;i++)
        {
            cin>>n;
            stack<int>s;
            r=1;
            for(j=1;j<=n;j++)
            {
                cin>>a[j];
            }
            for(j=1;j<=n;j++)
            {
                cin>>b[j];
            }
            for(j=1;j<=n;j++)
            {
                s.push(a[j]);
                while(s.empty()==0&&s.top()==b[r])
                {
                    s.pop();
                    r++;
                }
            }
            if(s.empty()==0)
            {
                cout<<"No"<<endl;
            }
            else
            {
                cout<<"Yes"<<endl;
            }
        }
        return 0;
    }
    

CF1331F Elementary!

  • 愚人节的题,建议去看官方题解要简化题意。

    点击查看代码
    string s,v[120]={" ","H","HE","LI","BE","B","C","N","O","F","NE","NA","MG","AL","SI","P","S","CL","AR","K","CA","SC","TI","V","CR","MN","FE","CO","NI","CU","ZN","GA","GE","AS","SE","BR","KR","RB","SR","Y","ZR","NB","MO","TC","RU","RH","PD","AG","CD","IN","SN","SB","TE","I","XE","CS","BA","LA","CE","PR","ND","PM","SM","EU","GD","TB","DY","HO","ER","TM","YB","LU","HF","TA","W","RE","OS","IR","PT","AU","HG","TL","PB","BI","PO","AT","RN","FR","RA","AC","TH","PA","U","NP","PU","AM","CM","BK","CF","ES","FM","MD","NO","LR","RF","DB","SG","BH","HS","MT","DS","RG","CN","NH","FL","MC","LV","TS","OG"};
    bool dfs(int x)
    {
        for(int i=1;i<=118;i++)
        {
            if(s.compare(x,v[i].size(),v[i])==0)
            {
                if(x+v[i].size()==s.size()||dfs(x+v[i].size())==true)
                {
                    return true;
                }
            }
        }
        return false;
    }
    int main()
    {
        cin>>s;
        if(dfs(0)==true)
        {
            cout<<"YES"<<endl;
        }
        else
        {
            cout<<"NO"<<endl;
        }
        return 0;
    }
    

2.13

闲话

做题纪要

CF656F Ace It!

  • 感谢万能的翻译。

    点击查看代码
    int main()
    {
        int ans=0;
        char c;
        while(cin>>c)
        {
            if(c=='A')
            {
                ans++;
            }
            else
            {
                if(c=='1')
                {
                    ans+=10;
                }
                else
                {
                    ans+=c-'0';
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

CF784F Crunching Numbers Just for You

  • 每个测试点用时必须在 \(1s\) 以上。

    点击查看代码
    int a[11];
    int main()
    {
        int n,i;
        cin>>n;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        i=0;
        while(1.0*clock()/CLOCKS_PER_SEC<1.5)
        {
            i++;
        }
        sort(a+1,a+1+n);
        for(i=1;i<=n;i++)
        {
            cout<<a[i]<<" ";
        }
        return 0;
    }
    

CF656A Da Vinci Powers

  • OEIS 数列

    点击查看代码
    int main()
    {
        ll n,i,ans=1;
        cin>>n;
        for(i=1;i<=n;i++)
        {
            ans*=2;
            if(i==13)
            {
                ans-=100;
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

luogu P1723 高手过愚人节

  • 马拉车板子。

    点击查看代码
    int r[40000001];
    string s,t;
    int main()
    {
        int m,n,maxr,id,ans,i,j;
        cin>>m;
        for(i=1;i<=m;i++)
        {
            cin>>s;
            t=" #";
            maxr=id=ans=0;
            for(j=0;j<s.size();j++)
            {
                t+=s[j];
                t+="#";
            }
            n=t.size()-1;
            for(j=1;j<=n;j++)
            {
                r[j]=(j<maxr)?min(r[id-(j-id)],maxr-j):1;
                while(1<=j-r[j]&&j+r[j]<=n&&t[j-r[j]]==t[j+r[j]])
                {
                    r[j]++;
                }
                if(maxr<j+r[j])
                {
                    maxr=j+r[j];
                    id=j;
                }
            }
            for(j=1;j<=n;j++)
            {
                ans=max(ans,r[j]-1);
            }
            cout<<ans<<endl;
        }
        return 0;
    }
    

luogu P9606 [CERC2019] ABB

  • 多倍经验: UVA11475 Extend to Palindrome | SP4103 EPALIN - Extend to Palindrome

  • 等价于将原字符串 \(S\) 分成 \(A,B\) 两部分满足 \(A+B=S\) ,使得 \(B\) 为回文串,求 \(|S|-\max \{ |B| \}\)

  • 输出方案时,设 \(A\) 的反串为 \(A'\) ,有 \(A+B+A'=S+A'\) 即为所求。

    点击查看代码
    int r[1300001];
    string s,t=" #";
    int main()
    {
        int lens,n,maxr=0,id=0,ans=0,i;
        cin>>lens>>s;
        for(i=0;i<s.size();i++)
        {
            t+=s[i];
            t+='#';
        }
        n=t.size()-1;
        for(i=1;i<=n;i++)
        {
            r[i]=(i<maxr)?min(r[id-(i-id)],maxr-i):1;
            while(1<=i-r[i]&&i+r[i]<=n&&t[i-r[i]]==t[i+r[i]])
            {
                r[i]++;
            }
            if(maxr<i+r[i])
            {
                maxr=i+r[i];
                id=i;
            }
            if(i+r[i]-1==n)
            {
                ans=r[i]-1;
                break;
            }
        }
        cout<<lens-ans<<endl;
        return 0;
    }
    

UVA1328 Period

  • 多倍经验: SP263 PERIOD - Period

  • 记得对循环节数量 \(>1\) 进行特判。

    点击查看代码
    int nxt[10000002];
    char s[1000002];
    int main()
    {
        int n,cnt=0,i,j;
        while(cin>>n)
        {
            if(n==0)
            {
                break;
            }
            else
            {
                cin>>(s+1);
                cnt++;
                cout<<"Test case #"<<cnt<<endl;
                for(i=2,nxt[1]=j=0;i<=n;i++)
                {
                    while(j>=1&&s[i]!=s[j+1])
                    {
                        j=nxt[j];
                    }
                    j+=(s[i]==s[j+1]);
                    nxt[i]=j;
                    if(i%(i-nxt[i])==0&&i/(i-nxt[i])>=2)
                    {
                        cout<<i<<" "<<i/(i-nxt[i])<<endl;	
                    }
                }
                cout<<endl;
            }
        }
        return 0;
    }
    

UVA12467 Secret Word

SP34020 ADAPET - Ada and Pet

2.14

闲话

做题纪要

CF1200E Compress Words

  • 从贪心的角度分析,我们发现 \(KMP\) 的最大匹配长度不会超过待拼接串的长度,故对 \(ans_{|ans|-min(|S|,|ans|)+1 \sim |ans|}\)\(S_{1 \sim |S|}\) 进行匹配即可。然后进行拼接即可。

    点击查看代码
    int nxt[1000002];
    char s[1000002],ans[1000002];
    int main()
    {
        int n,m,i,j,k,lenans;
        cin>>m>>(ans+1);
        lenans=strlen(ans+1);
        for(k=2;k<=m;k++)
        {
            cin>>(s+1);
            n=strlen(s+1);
            for(i=2,nxt[1]=j=0;i<=n;i++)
            {
                while(j>=1&&s[i]!=s[j+1])
                {
                    j=nxt[j];
                }
                j+=(s[i]==s[j+1]);
                nxt[i]=j;
            }
            for(i=lenans-min(lenans,n)+1,j=0;i<=lenans;i++)
            {
                while(j>=1&&ans[i]!=s[j+1])
                {
                    j=nxt[j];
                }
                j+=(ans[i]==s[j+1]);
            }
            for(i=j+1;i<=n;i++)
            {
                lenans++;
                ans[lenans]=s[i];
            }
        }
        for(i=1;i<=lenans;i++)
        {
            cout<<ans[i];
        }
        return 0;
    }
    

CF471D MUH and Cube Walls

  • \(a,b\) 的差分数组跑一遍 \(KMP\) 即可。

  • 记得对 \(w=1\) 进行特判。

    点击查看代码
    int a[200002],b[200002],s1[200002],s2[200002],nxt[200002];
    int main()
    {
        int n,m,i,j,ans=0;
        cin>>n>>m;
        for(i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        for(i=1;i<=n-1;i++)
        {
            s1[i]=a[i+1]-a[i];
        }
        for(i=1;i<=m;i++)
        {
            cin>>b[i];
        }
        for(i=1;i<=m-1;i++)
        {
            s2[i]=b[i+1]-b[i];
        }
        if(m==1)
        {
            ans=n;
        }
        else
        {
            for(i=2,nxt[1]=j=0;i<=m-1;i++)
            {
                while(j>=1&&s2[i]!=s2[j+1])
                {
                    j=nxt[j];
                }
                j+=(s2[i]==s2[j+1]);
                nxt[i]=j;
            }
            for(i=1,j=0;i<=n-1;i++)
            {
                while(j>=1&&s1[i]!=s2[j+1])
                {
                    j=nxt[j];
                }
                j+=(s1[i]==s2[j+1]);
                if(j==m-1)
                {
                    ans++;
                    j=nxt[m-1];
                }
            }
        }
        cout<<ans<<endl;
        return 0;
    }
    

[ABC339F] Product Equality

  • 双哈希板子。

    点击查看代码
    #define ll __int128_t
    const ll mod1=1000000000000000003,mod2=100000000000001093,base=10;
    map<ll,ll>vis[4];
    ll a[1002][4][1002],len[1002],jc[4][1002];
    char s[1002];
    ll read()
    {
        ll x=0,f=1;
        char c=getchar();
        while(c>'9'||c<'0')
        {
            if(c=='-')
            {
                f=-1;
            }
            c=getchar();
        }
        while('0'<=c&&c<='9')
        {
            x=x*10+c-'0';
            c=getchar();
        }
        return x*f;
    }
    void write(ll x)
    {
        if(x<0)
        {
            putchar('-');
            x=-x;
        }
        if(x>9)
        {
            write(x/10);
        }
        putchar((x%10)+'0');
    }
    void sx_hash(char s[],ll a[],ll len,ll mod)
    {
        for(ll i=0;i<=len;i++)
        {
            a[i]=(i==0)?0:((a[i-1]*base%mod+s[i]-'0')%mod);
        }
    }
    ll ask_hash(ll a[],ll jc[],ll l,ll r,ll mod)
    {
        return (a[r]-a[l-1]*jc[r-l+1]%mod+mod)%mod;
    }
    int main()
    {
        ll n,ans=0,i,j;
        n=read();
        for(i=0;i<=1000;i++)
        {
            jc[1][i]=(i==0)?1:(jc[1][i-1]*base%mod1);
            jc[2][i]=(i==0)?1:(jc[2][i-1]*base%mod2);
            jc[3][i]=(i==0)?1:(jc[3][i-1]*base%mod2);
        }
        for(i=1;i<=n;i++)
        {
            cin>>(s+1);
            len[i]=strlen(s+1);
            sx_hash(s,a[i][1],len[i],mod1);
            vis[1][ask_hash(a[i][1],jc[1],1,len[i],mod1)]++;
            sx_hash(s,a[i][2],len[i],mod2);
            vis[2][ask_hash(a[i][2],jc[2],1,len[i],mod2)]++;
        }
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                if(vis[1].find(ask_hash(a[i][1],jc[1],1,len[i],mod1)*ask_hash(a[j][1],jc[1],1,len[j],mod1)%mod1)!=vis[1].end()&&vis[2].find(ask_hash(a[i][2],jc[2],1,len[i],mod2)*ask_hash(a[j][2],jc[2],1,len[j],mod2)%mod2)!=vis[2].end())
                {
                    if(vis[1][ask_hash(a[i][1],jc[1],1,len[i],mod1)*ask_hash(a[j][1],jc[1],1,len[j],mod1)%mod1]==vis[2][ask_hash(a[i][2],jc[2],1,len[i],mod2)*ask_hash(a[j][2],jc[2],1,len[j],mod2)%mod2])
                    {
                        ans+=vis[1][ask_hash(a[i][1],jc[1],1,len[i],mod1)*ask_hash(a[j][1],jc[1],1,len[j],mod1)%mod1];
                    }
                }
            }
        }
        write(ans);
        return 0;
    }
    

[ABC331F] Palindrome Query

  • 若一个字符串为回文串,则原串哈希值等于其反串的哈希值。

  • 线段树维护原串和反串的哈希值即可。

    点击查看代码
    const ll base=13331;
    ull jc[5000001];
    char s[5000001];
    struct SegmentTree
    {
        ull l,r,sum[2],len;
    }tree[5000001];
    ull lson(ull x)
    {
        return x*2;
    }
    ull rson(ull x)
    {
        return x*2+1;
    }
    void pushup(ull rt)
    {
        tree[rt].sum[0]=tree[lson(rt)].sum[0]*jc[tree[rson(rt)].len]+tree[rson(rt)].sum[0];
        tree[rt].sum[1]=tree[rson(rt)].sum[1]*jc[tree[lson(rt)].len]+tree[lson(rt)].sum[1];
        tree[rt].len=tree[lson(rt)].len+tree[rson(rt)].len;
    }
    void build(ull rt,ull l,ull r)
    {
        tree[rt].l=l;
        tree[rt].r=r;
        if(l==r)
        {
            tree[rt].sum[0]=tree[rt].sum[1]=s[l];
            tree[rt].len=1;
            return ;
        }
        ull mid=(l+r)/2;
        build(lson(rt),l,mid);
        build(rson(rt),mid+1,r);
        pushup(rt);
    }
    void update(ull rt,ull pos,ull val)
    {
        if(tree[rt].l==tree[rt].r)
        {
            tree[rt].sum[0]=tree[rt].sum[1]=val;
            return ;
        }
        ull mid=(tree[rt].l+tree[rt].r)/2;
        if(pos<=mid)
        {
            update(lson(rt),pos,val);
        }
        else
        {
            update(rson(rt),pos,val);
        }
        pushup(rt);
    }
    pair<ull,ull> query1(ull rt,ull l,ull r)
    {
        if(l<=tree[rt].l&&tree[rt].r<=r)
        {
            return make_pair(tree[rt].sum[0],tree[rt].len);
        }
        ull mid=(tree[rt].l+tree[rt].r)/2;
        pair<ull,ull>lans=make_pair(0,0),rans=make_pair(0,0);
        if(l<=mid)
        {
            lans=query1(lson(rt),l,r);
        }
        if(r>mid)
        {
            rans=query1(rson(rt),l,r);
        }
        return make_pair(lans.first*jc[rans.second]+rans.first,lans.second+rans.second);
    }
    pair<ull,ull> query2(ull rt,ull l,ull r)
    {
        if(l<=tree[rt].l&&tree[rt].r<=r)
        {
            return make_pair(tree[rt].sum[1],tree[rt].len);
        }
        ull mid=(tree[rt].l+tree[rt].r)/2;
        pair<ull,ull>lans=make_pair(0,0),rans=make_pair(0,0);
        if(l<=mid)
        {
            lans=query2(lson(rt),l,r);
        }
        if(r>mid)
        {
            rans=query2(rson(rt),l,r);
        }
        return make_pair(rans.first*jc[lans.second]+lans.first,lans.second+rans.second);
    }
    int main()
    {
        ull n,m,l,r,pd,i;
        char c;
        cin>>n>>m>>(s+1);
        for(i=0;i<=n;i++)
        {
            jc[i]=(i==0)?1:(jc[i-1]*base);
        }
        build(1,1,n);
        for(i=1;i<=m;i++)
        {
            cin>>pd>>l;
            if(pd==1)
            {
                cin>>c;
                update(1,l,c);
            }
            if(pd==2)
            {
                cin>>r;
                if(query1(1,l,r).first==query2(1,l,r).first)
                {
                    cout<<"Yes"<<endl;
                }
                else
                {
                    cout<<"No"<<endl;
                }
            }
        }
        return 0;
    }
    
posted @ 2024-02-14 11:26  hzoi_Shadow  阅读(45)  评论(0编辑  收藏  举报
扩大
缩小