time limit per test2.5 seconds

memory limit per test512 megabytes

inputstandard input

outputstandard output

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.

Examples

input

6

123434

output

8

input

8

20152016

output

4

Note

In the first sample there are 8 ways to split the sequence:

“123434” = “123434” (maybe the given sequence is just one big number)

“123434” = “1” + “23434”

“123434” = “12” + “3434”

“123434” = “123” + “434”

“123434” = “1” + “23” + “434”

“123434” = “1” + “2” + “3434”

“123434” = “1” + “2” + “3” + “434”

“123434” = “1” + “2” + “3” + “4” + “34”

Note that we don’t count a split “123434” = “12” + “34” + “34” because numbers have to be strictly increasing.

In the second sample there are 4 ways:

“20152016” = “20152016”

“20152016” = “20” + “152016”

“20152016” = “201” + “52016”

“20152016” = “2015” + “2016”

【题解】



用记忆化搜索来搞;

int f(int x,int len);

表示当前的下标为x,然后把x->x+len-1这一段化为一段的方案数;

(这整个int可以理解为以x为左端点,长度不小于len的方案数);

一开始调用f(1,1);

表示获取以1为左端点,长度不小于1的方案数;

具体实现如下

int f(int x,int len)
{
if (s[x]=='0')//如果这个数字为0则范围方案数为0
return 0;
if (x+len-1 > n)//如果这一段划分超过了边界则无解
return 0;
if (x+len-1 == n)//如果恰好为n,那直接返回1
return 1;
if (ans[x][len]!=-1)//如果之前已经找过这个答案了;那么返回记录的答案;
return ans[x][len];
int ret = 0;
ret = f(x,len+1);//递归求解子问题比如f(1,2),f(1,3);
int a = get_lca(x,x+len);//这个表示以x..x+len-1这一段为一段;查看接下来要分那一段;这里的lca是x和x+len这两个位置后面相同的字符的个数->用于比较,从第一个不相同的数字开始比较
if (a>=len || (a<len && s[x+a]>=s[x+len+a]))//x+a和x+len+a分别是两个字符串第一个不同的位置的下标
ret+=f(x+len,len+1);//如果前面那个大于后面那个;则后面那个字符串只能通过增加一位长度来比它大
else
ret+=f(x+len,len);//否则,因为后面那个比较大,所以长度可以一样;
if (ret >= MOD) ret-=MOD;//加法的取模可以直接减掉;
ans[x][len] = ret;//记录答案;
return ret;
}

完整代码↓↓

#include <cstdio>
#include <cstdlib>
#include <cmath>
#include <set>
#include <map>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <queue>
#include <vector>
#include <stack>
#include <string>
#define lson L,m,rt<<1
#define rson m+1,R,rt<<1|1
#define LL long long using namespace std; const int MAXN = 5010;
const int MOD = 1e9+7;
const int dx[5] = {0,1,-1,0,0};
const int dy[5] = {0,0,0,-1,1};
const double pi = acos(-1.0); int n,lca[MAXN][MAXN],ans[MAXN][MAXN];
char s[MAXN]; void input_LL(LL &r)
{
r = 0;
char t = getchar();
while (!isdigit(t) && t!='-') t = getchar();
LL sign = 1;
if (t == '-')sign = -1;
while (!isdigit(t)) t = getchar();
while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
r = r*sign;
} void input_int(int &r)
{
r = 0;
char t = getchar();
while (!isdigit(t)&&t!='-') t = getchar();
int sign = 1;
if (t == '-')sign = -1;
while (!isdigit(t)) t = getchar();
while (isdigit(t)) r = r * 10 + t - '0', t = getchar();
r = r*sign;
} int get_lca(int x,int y)
{
if (x > n || y>n)
return 0;
if (lca[x][y]!=-1)
return lca[x][y];
int ret = 0;
if (s[x]==s[y])
ret += get_lca(x+1,y+1)+1;
lca[x][y] = ret;
return ret;
} int f(int x,int len)
{
if (s[x]=='0')
return 0;
if (x+len-1 > n)
return 0;
if (x+len-1 == n)
return 1;
if (ans[x][len]!=-1)
return ans[x][len];
int ret = 0;
ret = f(x,len+1);
int a = get_lca(x,x+len);
if (a>=len || (a<len && s[x+a]>=s[x+len+a]))
ret+=f(x+len,len+1);
else
ret+=f(x+len,len);
if (ret >= MOD) ret-=MOD;
ans[x][len] = ret;
return ret;
} int main()
{
//freopen("F:\\rush.txt","r",stdin);
memset(lca,255,sizeof(lca));
memset(ans,255,sizeof(ans));
input_int(n);
scanf("%s",s+1);
printf("%d",f(1,1));
return 0;
}

最新文章

  1. div实现自适应高度的textarea,实现angular双向绑定
  2. wamp2.5 局域网无法访问问题
  3. [C#对Oracle操作]C#操作调用Orcale存储过程有参数
  4. uploadify springMVC
  5. JS魔法堂:那些困扰你的DOM集合类型
  6. mysql实时同步到mssql的解决方案
  7. hdu 5755(高斯消元——模线性方程组模板)
  8. css怎么引用某张图片?链接要怎么写
  9. mac 键盘特殊标记
  10. [Aaronyang] 写给自己的WPF4.5 笔记15[AyArc诞生-WPF版本绚丽的环状图,Ay制作,AyWindow强势预览]
  11. CyclicBarrier和CountDownLatch介绍
  12. python之HTMLParser解析HTML文档
  13. Spring Cache For Redis
  14. Java HashMap的扩容
  15. 【Java编程】Java中的字符串匹配
  16. 前后台分离部署时,Niginx上的部署
  17. discuss!X3.4 帖子显示昵称而不是用户名的解决办法
  18. MBG逆向工程报错:generate failed: Exception getting JDBC Driver: com.mysql.jdbc.Driver
  19. C51 玄学问题,magic
  20. yolo源码解析(一)

热门文章

  1. 【CS Round #48 (Div. 2 only)】8 Divisible
  2. 加固linux
  3. [React Intl] Render Content Based on a Number using react-intl FormattedMessage (plural)
  4. java程序猿经常使用的工具名称--知道中文意思吗
  5. Maven报错Missing artifact jdk.tools:jdk.tools:jar:1.7--转
  6. [Angular] Step-By-Step Implementation of a Structural Directive - Learn ViewContainerRef
  7. Visual Studio中你所不知道的智能感知
  8. 15、USB摄像头图片采集+QT显示
  9. webuploader 小demo
  10. java异常——捕获异常+再次抛出异常与异常链