• Codeforces Good Bye 2015 D. New Year and Ancient Prophecy 后缀数组 树状数组 dp


    D. New Year and Ancient Prophecy

    题目连接:

    http://www.codeforces.com/contest/611/problem/C

    Description

    Limak is a little polar bear. In the snow he found a scroll with the ancient prophecy. Limak doesn't know any ancient languages and thus is unable to understand the prophecy. But he knows digits!

    One fragment of the prophecy is a sequence of n digits. The first digit isn't zero. Limak thinks that it's a list of some special years. It's hard to see any commas or spaces, so maybe ancient people didn't use them. Now Limak wonders what years are listed there.

    Limak assumes three things:

    Years are listed in the strictly increasing order;

    Every year is a positive integer number;

    There are no leading zeros.

    Limak is going to consider all possible ways to split a sequence into numbers (years), satisfying the conditions above. He will do it without any help. However, he asked you to tell him the number of ways to do so. Since this number may be very large, you are only asked to calculate it modulo 109 + 7.

    Input

    The first line of the input contains a single integer n (1 ≤ n ≤ 5000) — the number of digits.

    The second line contains a string of digits and has length equal to n. It's guaranteed that the first digit is not '0'.

    Output

    Print the number of ways to correctly split the given sequence modulo 109 + 7.

    Sample Input

    6

    123434

    Sample Output

    8

    Hint

    题意:

    给你一个全是数字的字符串(长度5000),问你多少种划分方案,就可以使得这个字符串分割成了一个绝对递增序列。

    题解

    DP,dp[i][j]表示以i位置结尾,长度为j的字符串的方案数。转移很简单,就dp[i][j]+=dp[i-j]k,如果str[i-j+1][i]>str[i-j-j+1][i-j]的话,dp[i][j]+=dp[i-j][j]。
    很显然,dp是n^3的,我们就可以用奇怪的手法去优化一下就好了,我是无脑后缀数组预处理优化的。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    
    long long dp[5005][5005];
    char str[5005];
    const int mod = 1e9+7;
    char s[5005];
    struct Bit
    {
        int lowbit(int x)
        {
            return x&(-x);
        }
    
        long long val[5005];
        int sz;
    
        void init(int sz){
            this->sz=sz;
            for(int i = 0 ; i <= sz ; ++ i) val[i] = 0 ;
        }
    
        void updata(int pos ,long long key)
        {
            while(pos<=sz){
                val[pos]+=key;
                if(val[pos]>=mod)
                    val[pos]-=mod;
                pos+=lowbit(pos);
            }
        }
    
        long long query(int pos)
        {
            long long res=0;
            while(pos>0)
            {
                res+=val[pos];
                if(res>=mod)res-=mod;
                pos-=lowbit(pos);
            }
            return res;
        }
    
    }bit[5005];
    #define maxn 5005
    const int inf=0x3f3f3f3f;
    int wa[maxn],wb[maxn],wn[maxn],wv[maxn];
    int rk[maxn],height[maxn],sa[maxn],r[maxn],Min[maxn][20],ok[maxn][maxn],n;
    
    int cmp(int *r,int a,int b,int l)
    {
        return (r[a]==r[b])&&(r[a+l]==r[b+l]);
    }
    void da(int *r,int *sa,int n,int m)
    {
        int i,j,p,*x=wa,*y=wb,*t;
        for(i=0;i<m;i++) wn[i]=0;
        for(i=0;i<n;i++) wn[x[i]=r[i]]++;
        for(i=1;i<m;i++) wn[i]+=wn[i-1];
        for(i=n-1;i>=0;i--) sa[--wn[x[i]]]=i;
        for(j=1,p=1;p<n;j*=2,m=p)
        {
            for(p=0,i=n-j;i<n;i++) y[p++]=i;
            for(i=0;i<n;i++) if(sa[i]>=j) y[p++]=sa[i]-j;
            for(i=0;i<n;i++) wv[i]=x[y[i]];
            for(i=0;i<m;i++) wn[i]=0;
            for(i=0;i<n;i++) wn[wv[i]]++;
            for(i=1;i<m;i++) wn[i]+=wn[i-1];
            for(i=n-1;i>=0;i--) sa[--wn[wv[i]]]=y[i];
            for(t=x,x=y,y=t,p=1,x[sa[0]]=0,i=1;i<n;i++)
                x[sa[i]]=cmp(y,sa[i-1],sa[i],j)?p-1:p++;
        }
    }
    void calheight(int *r,int *sa,int n)
    {
        int i,j,k=0;
        for(i=1;i<=n;i++) rk[sa[i]]=i;
        for(i=0;i<n;height[rk[i++]]=k )
        for(k?k--:0,j=sa[rk[i]-1];r[i+k]==r[j+k];k++);
    }
    void makermq()
    {
        for(int i=1;i<=n;i++) Min[i][0]=height[i];
        for(int i=1;(1<<i)<=n;i++)
            for(int j=1;j+(1<<i)-1<=n;j++)
            {
                Min[j][i]=min(Min[j][i-1],Min[j+(1<<i-1)][i-1]);
            }
    }
    int ask(int a,int b)
    {
        int l=rk[a],r=rk[b];
        if(l>r) swap(l,r);
        l++;
        if(l>r) return n-a;
        int tmp=int(log(r-l+1)/log(2));
        return min(Min[l][tmp],Min[r-(1<<tmp)+1][tmp]);
    }
    int check(int r,int l,int r1,int l1)
    {
        r--,l--,r1--,l1--;
        if(r<0||l<0||r1<0||l1<0)return 0;
        if(ok[l1][r]==1)return 1;
        return 0;
    }
    long long updata(long long a,long long b)
    {
        return (a+b)%mod;
    }
    int main()
    {
        scanf("%d%s",&n,s+1);
        for(int i=0;i<n;i++)
            str[i]=s[i+1];
        for(int i=0;i<n;i++)
            r[i]=str[i];
        r[n]=0;
        da(r,sa,n+1,256);
        calheight(r,sa,n);
        makermq();
        for(int i = 0 ; i <= n ; ++ i) bit[i].init(n);
        for(int i = 0 ; i < n ; ++ i)
            for(int j = i + 1 ; j < n ; ++ j)
               if((j-i)%2==1){
                    int tmp=ask(i,i+(j-i+1)/2);
                    if(i+tmp>=i+(j-i+1)/2||str[i+tmp]>=str[i+(j-i+1)/2+tmp]) ok[i][j]=0;else ok[i][j]=1;
                }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=i;j++)
            {
                if(s[i-j+1] == '0')
                    continue;
                dp[i][j] = 0 ;
                if(i-j == 0) dp[i][j] ++ ;
                dp[i][j] += bit[i-j].query(j - 1);
                if(i-j!=0&&(i-j-j+1)>0){
                    if(ok[i-j-j][i-1])
                    dp[i][j] += bit[i-j].query(j)-bit[i-j].query(j-1);
                }
                if(dp[i][j]>=mod)dp[i][j]%=mod;
                bit[i].updata(j,dp[i][j]);
            }
        }
        cout<<bit[n].query(n)<<endl;
        return 0;
    }
  • 相关阅读:
    【Azure 应用服务】在Azure App Service多实例的情况下,如何在应用中通过代码获取到实例名(Instance ID)呢?
    【Azure 应用服务】App Service For Windows 中如何设置代理实现前端静态文件和后端Java Spring Boot Jar包
    【Azure Developer】使用Azure Key Vault 的Key签名后,离线验证的一些参考资料
    【Azure Function】调试 VS Code Javascript Function本地不能运行,报错 Value cannot be null. (Parameter 'provider')问题
    【Azure 应用服务】App Service 使用Tomcat运行Java应用,如何设置前端网页缓存的相应参数呢(Xms512m Xmx1204m)?
    【Azure API 管理】APIM添加Logtoeventhub的策略后,一些相关APIM与Event Hub的问题
    【Azure API 管理】为调用APIM的请求启用Trace 调试APIM Policy的利器
    【Azure 事件中心】China Azure上是否有Kafka服务简答
    【Azure 应用服务】探索在Azure上设置禁止任何人访问App Service的默认域名(Default URL)
    【Azure 微服务】记一次错误的更新Service Fabric 证书而引发的集群崩溃而只能重建
  • 原文地址:https://www.cnblogs.com/qscqesze/p/5091378.html
Copyright © 2020-2023  润新知