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;
}
Codeforces Good Bye 2015 D. New Year and Ancient Prophecy 后缀数组 树状数组 dp的更多相关文章
- Codeforces Round #365 (Div. 2) D - Mishka and Interesting sum(离线树状数组)
http://codeforces.com/contest/703/problem/D 题意: 给出一行数,有m次查询,每次查询输出区间内出现次数为偶数次的数字的异或和. 思路: 这儿利用一下异或和的 ...
- 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 ...
- 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 ...
- 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预处理出 ...
- 2015 CCPC-C-The Battle of Chibi (UESTC 1217)(动态规划+树状数组)
赛后当天学长就说了树状数组,结果在一个星期后赖床时才有了一点点思路…… 因为无法提交,不确定是否正确..嗯..有错希望指出,谢谢... 嗯..已经A了..提交地址http://acm.uestc.ed ...
- 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 ...
- 2015 北京网络赛 E Border Length hihoCoder 1231 树状数组 (2015-11-05 09:30)
#1231 : Border Length 时间限制:1000ms 单点时限:1000ms 内存限制:256MB 描述 Garlic-Counting Chicken is a special spe ...
- 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 ...
- Codeforces Round #590 (Div. 3)【D题:维护26棵树状数组【好题】】
A题 题意:给你 n 个数 , 你需要改变这些数使得这 n 个数的值相等 , 并且要求改变后所有数的和需大于等于原来的所有数字的和 , 然后输出满足题意且改变后最小的数值. AC代码: #includ ...
随机推荐
- JAVA多线程一
介绍 线程是操作系统的最小单位,一个进程可以创建多个线程. 线程有五种状态,分别是新建.就绪.运行.阻塞.死亡状态. 多线程可以提高执行效率,但是如果单线程可以完成的任务,使用多线程反而会增加不必要的 ...
- sql server 安装后登录服务器
计算机名\数据库实例名 z*******f-PC\zzf
- 记录一次cefsharp1输入法在win7下异常解决定位
最近几天都被基于cefSharp封装的浏览器控件搞疯了!对于cefSharp基本满足当前所做项目的需求,但是有一个问题一直困扰我,那就是系统中偶尔会出现输入法不能转换到中文.而且这个问题似乎没有什么规 ...
- 链接服务器"(null)"的 OLE DB 访问接口 "Microsoft.Jet.OLEDB.4.0" 返回了消息 "未指定的错误"。[手稿]
消息 7302,级别 16,状态 1,第 1 行 无法创建链接服务器 "(null)" 的 OLE DB 访问接口 "Microsoft.JET.OLEDB.4.0&qu ...
- Java多线程的五种状态
新建状态:new Thread(参数)之后,建立了一个线程对象; 就绪状态:线程对象建立之后,调用start()方法,进入就绪状态,此时并不会直接调用run()方法,线程进入运行状态还需要抢占CPU资 ...
- hive 面试题 转载
转自:http://blog.csdn.net/ningguixin/article/details/12852051 有一张很大的表:TRLOG该表大概有2T左右TRLOG:CREATE TABLE ...
- Python开发者最常犯的10个错误
Python是一门简单易学的编程语言,语法简洁而清晰,并且拥有丰富和强大的类库.与其它大多数程序设计语言使用大括号不一样 ,它使用缩进来定义语句块. 在平时的工作中,Python开发者很容易犯一些小错 ...
- 初识 istringstream、ostringstream、stringstream 运用
今天编程练习时遇到了istringstream的用法,感觉很实用.后面附题目! C++的输入输出分为三种: (1)基于控制台的I/O (2)基于文件的I/O (3)基于字符串的I/O 1.头文件 # ...
- [Lua]入门教程
什么是Lua Lua 是一个小巧的脚本语言.是巴西里约热内卢天主教大学(Pontifical Catholic University of Rio de Janeiro)里的一个研究小组,由Rober ...
- C# html互转mht
using System;using System.Runtime.InteropServices;using System.Text;using System.IO;namespace HTMLCo ...