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;
}

Codeforces Good Bye 2015 D. New Year and Ancient Prophecy 后缀数组 树状数组 dp的更多相关文章

  1. Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)

    http://codeforces.com/contest/703/problem/D 题意: 给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和. 思路: 这儿利用一下异或和的 ...

  2. Good Bye 2015 D. New Year and Ancient Prophecy

    D. New Year and Ancient Prophecy time limit per test 2.5 seconds memory limit per test 512 megabytes ...

  3. Codeforces Round #227 (Div. 2) E. George and Cards set内二分+树状数组

    E. George and Cards   George is a cat, so he loves playing very much. Vitaly put n cards in a row in ...

  4. Codeforces Round #261 (Div. 2) D. Pashmak and Parmida's problem (树状数组求逆序数 变形)

    题目链接 题意:给出数组A,定义f(l,r,x)为A[]的下标l到r之间,等于x的元素数.i和j符合f(1,i,a[i])>f(j,n,a[j]),求i和j的种类数. 我们可以用map预处理出  ...

  5. 2015 CCPC-C-The Battle of Chibi (UESTC 1217)(动态规划+树状数组)

    赛后当天学长就说了树状数组,结果在一个星期后赖床时才有了一点点思路…… 因为无法提交,不确定是否正确..嗯..有错希望指出,谢谢... 嗯..已经A了..提交地址http://acm.uestc.ed ...

  6. Codeforces Round #263 (Div. 1) C. Appleman and a Sheet of Paper 树状数组暴力更新

    C. Appleman and a Sheet of Paper   Appleman has a very big sheet of paper. This sheet has a form of ...

  7. 2015 北京网络赛 E Border Length hihoCoder 1231 树状数组 (2015-11-05 09:30)

    #1231 : Border Length 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Garlic-Counting Chicken is a special spe ...

  8. Codeforces Round #381 (Div. 2) D. Alyona and a tree dfs序+树状数组

    D. Alyona and a tree time limit per test 2 seconds memory limit per test 256 megabytes input standar ...

  9. Codeforces Round #590 (Div. 3)【D题:维护26棵树状数组【好题】】

    A题 题意:给你 n 个数 , 你需要改变这些数使得这 n 个数的值相等 , 并且要求改变后所有数的和需大于等于原来的所有数字的和 , 然后输出满足题意且改变后最小的数值. AC代码: #includ ...

随机推荐

  1. 【LeetCode】9 & 234 & 206 - Palindrome Number & Palindrome Linked List & Reverse Linked List

    9 - Palindrome Number Determine whether an integer is a palindrome. Do this without extra space. Som ...

  2. 二叉树单色路径最长&&穿珠子

    对树的操作,特别理解递归的好处. //对于一棵由黑白点组成的二叉树,我们需要找到其中最长的单色简单路径,其中简单路径的定义是从树上的某点开始沿树边走不重复的点到树上的 //另一点结束而形成的路径,而路 ...

  3. 在CENTOS下安装ORACLE 11g(LT项目开发参考)

    前段时间为K3CLOUD项目安装ORACLE服务器,因有同事对LINUX和ORACLE不熟,现整理文档,方便后面维护人员参考 ORACLE的安装 1.首先安装依赖包(新安装的centos需要,现服务器 ...

  4. MyEclipse2015对Javascript自动提示的终极支持

    2015通过集成Tern.js,进入了JS自动提示的最新时代 先看看具体效果吧:   点击链接会进入:   而tern.js已经支持相当多的框架:   关键这个提示不只是纯粹的js文件,对于jsp等等 ...

  5. 笔记:修改centos的IP地址相关配置

    最近碰到不少认识的人问相关问题 索性做个笔记 图个方便 修改eth0的网卡配置vi /etc/sysconfig/network-scripts/ifcfg-eth0DEVICE=eth0BOOTPR ...

  6. 成为IBM精英讲师-一分耕耘 一份收获 同时也多了一份责任!

    成为IBM精英讲师 一分耕耘 一份收获 同时也多了一份责任! http://www.webspherechina.net/?action-iste-type-lecturerlist 650) thi ...

  7. Chef

    Chef是一个渐渐流行的部署大.小集群的自动化管理平台.Chef可以用来管理一个传统的静态集群,也可以和EC2或者其他的云计算提供商一起使用.Chef用cookbook作为最基本的配置单元,可以被泛化 ...

  8. HTML5每日一练之OL列表的改良

    在HTML5中的OL被改良了,为它增加了两个新属性. start属性:start属性用来定义列表编号的起始位置,比如下面的代码,列表将从50开始51...55以此类推 <ol start=&qu ...

  9. JS的一些小验证

    1,文本框只能输入数字代码(小数点也不能输入) <input onkeyup="this.value=this.value.replace(/\D/g,'')" onafte ...

  10. CCF 201312-4 有趣的数 (数位DP, 状压DP, 组合数学+暴力枚举, 推公式, 矩阵快速幂)

    问题描述 我们把一个数称为有趣的,当且仅当: 1. 它的数字只包含0, 1, 2, 3,且这四个数字都出现过至少一次. 2. 所有的0都出现在所有的1之前,而所有的2都出现在所有的3之前. 3. 最高 ...