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. 通过HttpClient来调用Web Api接口

    回到目录 HttpClient是一个被封装好的类,主要用于Http的通讯,它在.net,java,oc中都有被实现,当然,我只会.net,所以,只讲.net中的HttpClient去调用Web Api ...

  2. 二级指针的作用及用途 .xml

    pre{ line-height:1; color:#9f1d66; background-color:#e1e1e1; font-size:16px;}.sysFunc{color:#5d57ff; ...

  3. 记一个社交APP的开发过程——基础架构选型(转自一位大哥)

    记一个社交APP的开发过程——基础架构选型 目录[-] 基本产品形态 技术选型 最近两周在忙于开发一个社交App,因为之前做过一点儿社交方面的东西,就被拉去做API后端了,一个人头一次完整的去搭这么一 ...

  4. Firefox 对条件判断语句块内的函数声明的处理与其他浏览器有差异

    标准参考 函数声明和函数表达式 定义一个函数有两种途径:函数声明和函数表达式. 函数声明: function Identifier ( FormalParameterList opt ) { Func ...

  5. 转-问自己:UI设计注意的十个问题

    UI 设计需要自问的 10个问题   UI 设计的魅力在于,你不仅需要适当的技巧,更要理解用户与程序的关系.一个有效的用户界面关注的是用户目标的实现,包括视觉元素与功能操作在内的所有东西都需要完整一致 ...

  6. 【转】内网yum源搭建

    我们内网yum要玩的话,先加hosts,然后找运维要CentOS_base.repo这个文件,然后yum clean all   && yum makecache ========== ...

  7. 应用dom4j读取xml的例子

    1. 样例xml <?xml version="1.0" encoding="UTF-8"?> <students> <stude ...

  8. c语言typedef的用法-解惑阿!很多天书般的东西解释的不错(转)

    转自(http://www.cnblogs.com/wchhuangya/archive/2009/12/25/1632160.html) 一.基本概念剖析 int* (*a[5])(int, cha ...

  9. 研究QGIS二次开发笔记(一)

    为了在QT程序中嵌入一个地图,最终选择了QGIS来干这件事.选型阶段真是呵呵.我折腾的是QGIS2.4.0. 首先,到官方网站下载安装QGIS.如果你跟我一样懒的话,可能希望下载一个已经编译好的win ...

  10. POJ3253Fence Repair(优先队列或单调队列)

    http://poj.org/problem?id=3253 经典题目了,大意是说如果要切断一个长度为a的木条需要花费代价a, 问要切出要求的n个木条所需的最小代价. 无论是以下哪种方法,最原始的思路 ...