T3还没有打出来,就先放两道。

----------------------------------------------------------

T1:密码破译

  温温手下的情报部门截获了一封加密信息,这个信息可以用长度为n的由小写字母构成的一个字符串表示。为了破译这个重要情报,温温决定亲自出马。

通过不懈研究,温温推测出了这封密文是怎样被构造出来的。

  首先选择一个长度大于4的“根”字符串,然后在“根”字符串之后连接上任意个长度为2或3的“后缀”字符串。构造唯一的限制条件是,不可以连续接上两个相同的“后缀”字符串

  现在温温想要知道,在这封密文的构造过程中,有可能被用作“后缀”的字符串共有多少种。多个同样的“后缀”字符串只算一种。

Input

一行,一个长度为n的仅包含小写字母的字符串

5 ≤ n ≤ 100 for 40%

5 ≤ n ≤ 10000 for 100%

Output

第一行一个整数k,表示有k种可能的“后缀”。

接下来k行,按照字典序依次输出所有可能的“后缀”。

Examples

input

abcdefghij

output

5

fg

fgh

gh

hij

ij

input

abaca

output

0

 

Note

在第一个样例中,有五种切分方式:

·abcdefgh/ij

·abcdefg/hij

·abcdef/gh/ij

·abcde/fgh/ij

·abcde/fg/hij

  

  这个题当时做的时候没有看到不准重复的限制条件,当时交上去代码不知道为什么没测,估计只有20分。

  一个关键的问题:如果出现了两个重复的连续后缀,靠后的那一个后缀是可以合法的,因为我们可以把前面的部分都算给“根”字符串;而前面的所有后缀都不合法。

  我们维护f[i][0/1]记录状态,分别表示从这个位置开始的长度为2、3的后缀是否可行。搞完麻烦的初始边界条件以后,转移更麻烦:既要保证这个串的下一个位置的0/1是否合法,也要看它和下一个后缀是否相同。判断合法后,我们直接把这个后缀插入一个set里:由于string定义的不等号是按字典序比较的,遍历set输出的元素实际上就是按字典序升序排列的。

代码:

  1. #include <iostream>
  2. #include <cstring>
  3. #include <cstdio>
  4. #include <cstdlib>
  5. #include <set>
  6. #define maxn 10010
  7. void open_file(std::string s) {
  8. std:: string In = s + ".in", Out = s + ".out";
  9. freopen(In.c_str(), "r", stdin);
  10. freopen(Out.c_str(), "w", stdout);
  11. }
  12. using namespace std;
  13. string s(1, 0), t;
  14. bool f[2][maxn];
  15. int len;
  16. set<string> S;
  17. void dp() {
  18. if (len < 7) {
  19. cout << 0;
  20. exit(0);
  21. }
  22. //  f[0][len] = f[1][len] = 0;
  23. string a(s.end() - 2, s.end());
  24. f[0][len - 1] = 1;
  25. S.insert(a);
  26. if (len >= 8) {
  27. f[1][len - 2] = 1;
  28. string b(s.end() - 3, s.end());
  29. S.insert(b);
  30. }
  31. for (int i = len - 3; i > 5; --i) {
  32. string t;
  33. for (int j = i; j <= i + 1; ++j)
  34. t.push_back(s[j]);
  35. if (f[0][i + 2] || f[1][i + 2])
  36. if (s[i] != s[i + 2] || s[i + 1] != s[i + 3])
  37. f[0][i] = 1, S.insert(t);
  38. t.push_back(s[i + 2]);
  39. if ((f[0][i + 3] || f[1][i + 3])
  40. && (s[i] != s[i + 3] || s[i + 1] != s[i + 4] || s[i + 2] != s[i + 5]))
  41. f[1][i] = 1, S.insert(t);
  42. }
  43. }
  44. int main() {
  45. open_file("suffix");
  46. ios::sync_with_stdio(0);
  47. getline(cin, t);
  48. s += t;
  49. len = s.size() - 1;
  50. dp();
  51. int size = S.size();
  52. cout << size << endl;
  53. set<string>::iterator it;
  54. int i = 1;
  55. for (it = S.begin(); i <= size; ++i, ++it)
  56. cout << *it << endl;
  57. return 0;
  58. }

----------------------------------------------------------

T2:先进序列

  

  萌猪大统领温温正在为他看到的所有事物评选先进。

温温已经评选出了n个先进整数ai,现在,他决定在此基础上评选一下先进序列。

一个整数序列x1,x2,…xk是先进的,当且仅当它满足以下三个条件

  1、这个序列是严格递增的。

  2、序列中,任意两个相邻的元素都不是互质的,即gcd(xi, xi+1) > 1对1 ≤ i < k成立。

  3、序列中的所有元素都是先进整数。

  现在温温想知道,最长的先进序列的长度是多少。

Input

第一行,一个整数n

第二行,n个整数ai,保证ai互不相同

1 ≤ ai ≤ 200000

1 ≤ n ≤ 1000 for 40%

1 ≤ n ≤ 100000 for 100%

Output

一个整数,最长先进序列的长度。

Examples

input

5

2 3 4 6 9

output

4

input

9

1 2 3 5 6 7 8 9 10

output

4

  (老师到底和温温有什么交易啊……三天都是一只猪

  今天的题难度确实比昨天小些,但是综合性很强。这个题的解法其实很显然,可是考场上看到数学就想打暴力……

  容易发现,我们应该把原序列进行升序排序后再按gcd的条件转移,这样就可以愉快地扫一遍来dp了。f[i]表示以位置i结尾的最长先进序列的长度,每找到一个位置,把这个数质因数分解。考虑之前含有质因子k的数的位置,开一个数组d[k]表示满足含k的位置的最大的f值。那么我们枚位置i的每一个素因子,拿之前记录的d数组+1来转移,然后再扫一遍,更新d数组的值。

  改的时候遇到一个坑点:sqrt函数不可以每次调用,否则复杂度会从O(nlog(sqrt(maxval)))退化到O(n^2)左右。

  既然写到这个题,就来重温一遍线性筛的写法。

  线性筛做到线性的关键,就是只用每个合数的最小质因子来筛掉它。

代码:

  1. void euler() {
  2. for (int i = 2; i <= maxv; ++i) {
  3. if (!vis[i]) prime[++prime[0]] = i;
  4. for (int j = 1; j <= prime[0] && prime[j] * i <= maxv; ++j) {
  5. vis[i * prime[j]] = 1;
  6. if (i % prime[j] == 0)
  7. break;
  8. }
  9. }
  10. }

  线性筛的正确性由以下两个重要性质来保证。

  1、素数k被选中以后,只会被乘上k、k+1,k+2……来筛掉它的倍数,之前的素数不会再被乘上。

  2、当我们选中的最小质数是i的因数时,以后的prime再乘上i,就一定能被prime[j]乘以某个数在以后筛掉,因此要把当前循环break掉。

T2代码:

  1. #include <cstdio>
  2. #include <iostream>
  3. #include <cstring>
  4. #include <cmath>
  5. #include <algorithm>
  6. #define maxn 100010
  7. void open_file(std::string s) {
  8. std:: string In = s + ".in", Out = s + ".out";
  9. freopen(In.c_str(), "r", stdin);
  10. freopen(Out.c_str(), "w", stdout);
  11. }
  12. const int maxv = 200010;
  13. using namespace std;
  14. int prime[maxv], a[maxn], n;
  15. bool vis[maxv];
  16. void euler() {
  17. for (int i = 2; i <= maxv; ++i) {
  18. if (!vis[i]) prime[++prime[0]] = i;
  19. for (int j = 1; j <= prime[0] && prime[j] * i <= maxv; ++j) {
  20. vis[i * prime[j]] = 1;
  21. if (i % prime[j] == 0)
  22. break;
  23. }
  24. }
  25. }
  26. int f[maxn], d[maxv];
  27. void dp() {
  28. for (register int i = 1; i <= n; ++i) {
  29. f[i] = 1;
  30. int k = sqrt(a[i]);
  31. for (register int j = 1; prime[j] <= k; ++j)
  32. if (a[i] % prime[j] == 0)
  33. f[i] = max(f[i], d[prime[j]] + 1),
  34. f[i] = max(f[i], d[a[i] / prime[j]] + 1);
  35. if (!vis[a[i]]) {
  36. f[i] = max(f[i], d[a[i]] + 1);
  37. d[a[i]] = max(d[a[i]], f[i]);
  38. }
  39. for (register int j = 1; prime[j] <= k; ++j)
  40. if (a[i] % prime[j] == 0)
  41. d[prime[j]] = max(d[prime[j]], f[i]),
  42. d[a[i] / prime[j]] = max(d[a[i] / prime[j]], f[i]);
  43. }
  44. return;
  45. }
  46. int main() {
  47. open_file("sequence");
  48. ios::sync_with_stdio(0);
  49. cin >> n;
  50. for (int i = 1; i <= n; ++i)
  51. cin >> a[i];
  52. euler();
  53. sort(a + 1, a + n + 1);
  54. dp();
  55. int ans = 0;
  56. for (int i = 1; i <= n; ++i)
  57. ans = max(ans, f[i]);
  58. cout << ans;
  59. return 0;
  60. }

【???】今天上午的考试题——区间dp和字符串/线性筛的综合应用的更多相关文章

  1. leetcode 730. 统计不同回文子序列(区间dp,字符串)

    题目链接 https://leetcode-cn.com/problems/count-different-palindromic-subsequences/ 题意 给定一个字符串,判断这个字符串中所 ...

  2. 动态规划——区间dp

    在利用动态规划解决的一些实际问题当中,一类是基于区间上进行的,总的来说,这种区间dp是属于线性dp的一种.但是我们为了更好的分类,这里仍将其单独拿出进行分析讨论. 让我们结合一个题目开始对区间dp的探 ...

  3. 动态规划——区间DP,计数类DP,数位统计DP

    本博客部分内容参考:<算法竞赛进阶指南> 一.区间DP 划重点: 以前所学过的线性DP一般从初始状态开始,沿着阶段的扩张向某个方向递推,直至计算出目标状态. 区间DP也属于线性DP的一种, ...

  4. 【BZOJ-1090】字符串折叠 区间DP + Hash

    1090: [SCOI2003]字符串折叠 Time Limit: 10 Sec  Memory Limit: 162 MBSubmit: 1127  Solved: 737[Submit][Stat ...

  5. 洛谷P4302 [SCOI2003]字符串折叠(区间dp)

    题意 题目链接 Sol 裸的区间dp. 转移的时候枚举一下断点.然后判断一下区间内的字符串是否循环即可 `cpp #include<bits/stdc++.h> #define Pair ...

  6. 【bzoj2121】字符串游戏 区间dp

    题目描述 给你一个字符串L和一个字符串集合S,如果S的某个子串在S集合中,那么可以将其删去,剩余的部分拼到一起成为新的L串.问:最后剩下的串长度的最小值. 输入 输入的第一行包含一个字符串,表示L. ...

  7. 洛谷P4302 [SCOI]字符串折叠 [字符串,区间DP]

    题目传送门 字符串折叠 题目描述 折叠的定义如下: 一个字符串可以看成它自身的折叠.记作S = S X(S)是X(X>1)个S连接在一起的串的折叠.记作X(S) = SSSS…S(X个S). 如 ...

  8. hihoCoder #1320 : 压缩字符串 区间dp

    /** 题目:hihoCoder #1320 : 压缩字符串 链接:https://hihocoder.com/problemset/problem/1320 描述 小Hi希望压缩一个只包含大写字母' ...

  9. hdu 4632 子字符串统计的区间dp

    题意:查找这样的子回文字符串(未必连续,但是有从左向右的顺序)个数. 简单的区间dp,哎,以为很神奇的东西,其实也是dp,只是参数改为区间,没做过此类型的题,想不到用dp,以后就 知道了,若已经知道[ ...

随机推荐

  1. Docker部署Mysql, Tomcat, Nginx, Redis

    1. Mysql部署 问题及解决方案 容器内的网络和外部机器不能直接通信 外部机器和宿主机可以直接通信 宿主机和容器可以直接通信 当容器中的网络服务需要被外部机器访问时,可以将容器中提供服务的端口映射 ...

  2. Ubuntu下创建apt源

    1. 下载所需安装文件 sudo apt-get install soft name  安装并保存安装文件 或者 sudo apt-get source soft name      只下载安装文件 ...

  3. ArcGIS API for Javascript的Point clustering使用及默认符号无法显示问题

    1.将包含ClusterFeatureLayer.js文件的extras文件夹放在部署的arcgis api目录下,如下图. extras路径 2.使用ClusterFeatureLayer关键代码如 ...

  4. 管理Pod(rc,rs,deployment)

    1.概述 可以把容器想像成豆荚里的豆子,把一个或多个关系紧密的豆子包在一起就是豆荚(一个Pod).在k8s中我们不会直接操作容器,而是把容器包装成Pod再进行管理. 2.管理Pod a. 使用Repl ...

  5. day81:luffy:课程分类页面&课程信息页面&指定分类显示课程信息&分页显示课程信息

    目录 1.构建课程前端初始页面 2.course后端的准备工作 3.后端实现课程分类列表接口 4.前端发送请求-获取课程分类信息 5.后端实现课程列表信息的接口 6.前端显示列表课程信息 7.按照指定 ...

  6. Django实现文件上传功能

    文件上传 关注公众号"轻松学编程"了解更多. 1.创建上传文件夹 在static文件夹下创建uploads用于存储接收上传的文件 在settings中配置,MEDIA_ROOT=o ...

  7. Spring框架之beans源码完全解析

    导读:Spring可以说是Java企业开发里最重要的技术.而Spring两大核心IOC(Inversion of Control控制反转)和AOP(Aspect Oriented Programmin ...

  8. 学了Java才搞懂JMeter测试计划

    本文的内容是对这个界面的东西进行讲解: Name 名字,测试计划总得有个名字. Comments 注释,除了名字,还得让人知道它是干嘛的. User Defined Variables 测试计划是根节 ...

  9. php ci下添加一个创建常用的模块和控制器方法

    我这么写是非常不好的 ,这些都可以写在lirbraries里面 (ci就是这么干的) 我这里是自己用 大概一个模型 没那么多讲究 现在core/CodeIgniter.php 文件 if($modle ...

  10. leetcode105: jump-game-ii

    题目描述 给出一个非负整数数组,你最初在数组第一个元素的位置 数组中的元素代表你在这个位置可以跳跃的最大长度 你的目标是用最少的跳跃次数来到达数组的最后一个元素的位置 例如 给出数组 A =[2,3, ...