Good Bye 2015 D. New Year and Ancient Prophecy(dp+LCP)
2016-01-27 14:54
387 查看
题意:
给定一个N≤5×103的大数字,保证大数字的第一位不是0,现在要把它分割成数字序列,数字序列中的数字满足以下要求:
1.数字序列中的数字严格递增
2.数字序列中的数字都是正数且不含前导0
求分割的方法数
分析:
考虑f[i][j]:=大数字分割成数字序列,且最后一个数字为{i⋯j}的方法数
显然ans=∑ni=1f[i][n],枚举最后一个数字加和
假设前一个数字为{a⋯i−1},如果Llast<Lcur,这个数字必然满足要求
即(i−1)−a<j−i⇒a>2i−j−1⇒a≥2i−j,即f[i][j]+=∑i−1a=2i−jf[a][i−1],这个我们维护一个前缀和就好
对于这个唯一的Llast=Lcur,我们要快速判断其大小,只要维护一个lcp[i][j]就好
代码:
给定一个N≤5×103的大数字,保证大数字的第一位不是0,现在要把它分割成数字序列,数字序列中的数字满足以下要求:
1.数字序列中的数字严格递增
2.数字序列中的数字都是正数且不含前导0
求分割的方法数
分析:
考虑f[i][j]:=大数字分割成数字序列,且最后一个数字为{i⋯j}的方法数
显然ans=∑ni=1f[i][n],枚举最后一个数字加和
假设前一个数字为{a⋯i−1},如果Llast<Lcur,这个数字必然满足要求
即(i−1)−a<j−i⇒a>2i−j−1⇒a≥2i−j,即f[i][j]+=∑i−1a=2i−jf[a][i−1],这个我们维护一个前缀和就好
对于这个唯一的Llast=Lcur,我们要快速判断其大小,只要维护一个lcp[i][j]就好
代码:
// // Created by TaoSama on 2016-01-27 // Copyright (c) 2015 TaoSama. All rights reserved. // #pragma comment(linker, "/STACK:1024000000,1024000000") #include <algorithm> #include <cctype> #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <iomanip> #include <iostream> #include <map> #include <queue> #include <string> #include <set> #include <vector> using namespace std; #define pr(x) cout << #x << " = " << x << " " #define prln(x) cout << #x << " = " << x << endl const int N = 5e3 + 10, INF = 0x3f3f3f3f, MOD = 1e9 + 7; int n; char s ; int lcp , f , prefix ; void add(int &x, int y) { if((x += y) >= MOD) x -= MOD; } //prefix[i][j] = sum(f[1...i][j]) void update(int i, int j) { add(prefix[i][j], prefix[i - 1][j] + f[i][j]); } int sum(int k, int i, int j) { int ret = prefix[j][k] - prefix[max(i - 1, 0)][k]; if(ret < 0) ret += MOD; return ret; } bool smaller(int i, int j, int len) { if(lcp[i][j] >= len) return false; return s[i + lcp[i][j]] < s[j + lcp[i][j]]; } int main() { #ifdef LOCAL freopen("C:\\Users\\TaoSama\\Desktop\\in.txt", "r", stdin); // freopen("C:\\Users\\TaoSama\\Desktop\\out.txt","w",stdout); #endif ios_base::sync_with_stdio(0); while(scanf("%d%s", &n, s + 1) == 2) { memset(lcp, 0, sizeof lcp); for(int i = n; i; --i) for(int j = n; j; --j) if(s[i] == s[j]) lcp[i][j] = lcp[i + 1][j + 1] + 1; memset(prefix, 0, sizeof prefix); for(int i = 1; i <= n; ++i) f[1][i] = 1, update(1, i); for(int i = 2; i <= n; ++i) { for(int j = i; j <= n; ++j) { if(s[i] == '0') f[i][j] = 0; else { int len = j - i + 1; int b = i - 1, a = b - len + 1; f[i][j] = sum(b, a + 1, b); if(a > 0 && smaller(a, i, len)) add(f[i][j], sum(b, a, a)); } update(i, j); } } int ans = 0; for(int i = 1; i <= n; ++i) add(ans, f[i] ); printf("%d\n", ans); } return 0; }
相关文章推荐
- 基于Android中dp和px之间进行转换的实现代码
- Android中dip、dp、sp、pt和px的区别详解
- LFC1.0.0 版本发布
- Android px、dp、sp之间相互转换
- HP data protector软件学习1--基本角色与基本工作流程
- HP data protector软件学习2--软件组成与界面介绍
- android中像素单位dp、px、pt、sp的比较
- Android对px和dip进行尺寸转换的方法
- Android根据分辨率进行单位转换-(dp,sp转像素px)
- android 尺寸 dp,sp,px,dip,pt详解
- DP问题各种模型的状态转移方程
- POJ-1695-Magazine Delivery-dp
- nyoj-1216-整理图书-dp
- TYVJ1193 括号序列解题报告
- 对DP的一点感想
- TYVJ上一些DP的解题报告
- soj1005. Roll Playing Games
- 01背包问题
- LeetCode之Maximum Product Subarray
- DP Flow