戳这里看题目吧!

题目大意:给你一个长度为n(2<=n<=5000)的序列,没有重复的数字,序列中每个元素满足(0<=numi<=1e9)。求一个最长的数列满足差分值相同(除n=2外,可以看成等差数列)。输出这个最大长度。

算法梗概:DP。看了几篇博客都说算是个板子套路DP题。在做的时候也想到了DP,但是没找对状态。

     另外可以用其他算法来做这道题,后面慢慢补。先给出DP算法的代码和思路。

 #include<cstdio>
#include<algorithm>
const int maxn = 5e3 + ;
int dp[maxn][maxn],n,num[maxn];
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i){
scanf("%d",num+i);
for(int j=;j<=n;++j){
dp[i][j] = ;
}
}
std::sort(num+,num++n);
int ans = ;
for(int i=;i<=n-;++i){
int pre = i - ;
for(int j=i+;j<=n;++j){
  ///令d=num[j] - num[i],因为序列是递增的,所以num[i] - num[pre]在pre刚开始不满足条件时大于d,在pre刚好满足条件时等于d,继续遍历则小于d,后来的遍历是无意义的所以跳出即可
  while(pre > && num[j] - num[i] > num[i] - num[pre]) pre--;
  if(pre==) break;
  else if(pre > && num[j] - num[i] == num[i] - num[pre]) dp[i][j] = std::max(dp[i][j],dp[pre][i]+);
  ans = std::max(ans,dp[i][j]);
}
}
printf("%d\n",ans);
return ;
}

DP思路:dp[i][j]表示已下标i,j(i<j)为结尾两个元素的一个子序列的长。枚举i,以i+1开始向后遍历j,这样对于每对i,j我们可以求出他们的差,以这个差为标准,从i-1开始向前遍历记为pre,直到找到的pre和i,j满足num[j] - num[i] == num[i] - num[pre]。如果找到这样的num[pre]更新dp[i][j]即可。

状态转移方程:dp[i][j] = max(dp[i][j],dp[pre][i]+1)


直接用用等差数列的通项公式来暴力

 #include <cstdio>
#include <algorithm>
#include <set>
using namespace std;
const int maxn = 5e3+;
int num[maxn],n;
set<int> se;
int main()
{
scanf("%d",&n);
for(int i = ; i<=n; ++i)
{
scanf("%d",num+i);
se.insert(num[i]);
}
sort(num+,num+n+);
int ans = ,d,k;
for(int i=;i<=n;++i)
{
for(int j=i+;j<=n;++j)
{
k = ,d = num[j] - num[i];
if(!se.count(num[i] + ans*d)) continue;
while(se.count(num[i] + k*d)) k++;
ans = max(ans,k);
}
if(ans==n) break;
}
printf("%d\n",ans);
return ;
}

核心代码:

     k = ,d = num[j] - num[i];
if(!se.count(num[i] + ans*d)) continue;
while(se.count(num[i] + k*d)) k++;
ans = max(ans,k);

暴力思路:ak = a1 + (k-1)d;

     两层for循环来枚举a1和d,对于每对<a1,d>,枚举k来得到一个ak,判断ak是不是存在在序列中,存在继续枚举,否则更新答案。

请注意!!!  if(!se.count(num[i] + ans*d)) continue; 这行代码的作用,对于你已经更新到的答案ans,如果num[i] + ans*d都不存在,那么无法更新答案,所以跳过这层循环。

没有这行代码会TLE在test 57或者test 58,做题就死在了这里了。


还有些同学用了二分函数,其实和暴力的核心思想差不多,用二分函数优化很多,这里只给代码,不解释了如果暴力看懂了这个也就懂了

 #include<cstdio>
#include<algorithm>
const int maxn = 5e3 + ;
int dp[maxn][maxn],n,num[maxn];
int main()
{
scanf("%d",&n);
for(int i=;i<=n;++i) scanf("%d",num+i);
std::sort(num+,num++n); int ans = ,res,d,pos;
for(int i=;i<=n-;++i){
for(int j=i+;j<=n;++j){
d = num[j] - num[i];
res = ;
pos = std::lower_bound(num+j+,num+n+,num[i]+ans*d) - num;
if(num[pos]!=num[i]+ans*d) continue;
for(int k=j;k<=n-;){
pos = std::lower_bound(num+k+,num+n+,num[k]+d) - num;
if(num[pos]==num[k]+d){
k = pos;
res++;
}
else break;
}
ans = std::max(ans,res);
}
}
printf("%d\n",ans);
return ;
}

This’s all!如有错误,请评论指正谢谢!!

Gym 102082B : Arithmetic Progressions的更多相关文章

  1. [Educational Codeforces Round 16]D. Two Arithmetic Progressions

    [Educational Codeforces Round 16]D. Two Arithmetic Progressions 试题描述 You are given two arithmetic pr ...

  2. Dirichlet's Theorem on Arithmetic Progressions 分类: POJ 2015-06-12 21:07 7人阅读 评论(0) 收藏

    Dirichlet's Theorem on Arithmetic Progressions Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

  3. 洛谷P1214 [USACO1.4]等差数列 Arithmetic Progressions

    P1214 [USACO1.4]等差数列 Arithmetic Progressions• o 156通过o 463提交• 题目提供者该用户不存在• 标签USACO• 难度普及+/提高 提交 讨论 题 ...

  4. POJ 3006 Dirichlet's Theorem on Arithmetic Progressions (素数)

    Dirichlet's Theorem on Arithmetic Progressions Time Limit: 1000MS   Memory Limit: 65536K Total Submi ...

  5. poj 3006 Dirichlet's Theorem on Arithmetic Progressions【素数问题】

    题目地址:http://poj.org/problem?id=3006 刷了好多水题,来找回状态...... Dirichlet's Theorem on Arithmetic Progression ...

  6. (素数求解)I - Dirichlet&#39;s Theorem on Arithmetic Progressions(1.5.5)

    Time Limit:1000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit cid=1006#sta ...

  7. USACO 1.4 Arithmetic Progressions

    Arithmetic Progressions An arithmetic progression is a sequence of the form a, a+b, a+2b, ..., a+nb ...

  8. Educational Codeforces Round 16 D. Two Arithmetic Progressions (不互质中国剩余定理)

    Two Arithmetic Progressions 题目链接: http://codeforces.com/contest/710/problem/D Description You are gi ...

  9. 等差数列Arithmetic Progressions题解(USACO1.4)

    Arithmetic Progressions USACO1.4 An arithmetic progression is a sequence of the form a, a+b, a+2b, . ...

随机推荐

  1. 用 Flask 来写个轻博客 (19) — 以 Bcrypt 密文存储账户信息与实现用户登陆表单

    目录 目录 前文列表 修改 User Model Flask Bcrypt 将 Bcrypt 应用到 User Model 中 创建登陆表单 前文列表 用 Flask 来写个轻博客 (1) - 创建项 ...

  2. COALESCE 函数作用

    用途. 将空值替换成其他值 返回第一个非空值. 任意一个不为空的值.比较有用.

  3. Android深度探索-卷1第一章心得体会

     本章介绍了安卓系统移植与驱动开发的概述,安卓的系统架构有四层:1 Linux内核,2 c/c++代码库, 3 Android SDK API, 4 应用程序 在读的过程中看到了专业名词,查了查,长点 ...

  4. python使用消息队列RabbitMq(入门)

    windows平台开发和使用 安装 安装Erlang:https://pan.baidu.com/s/1QcZDaI205uaue7mMWh5cSA 安装RabbitMQ:https://pan.ba ...

  5. 哈希算法和字典类的定义,DataSet中数据遍历的几种方法

    哈希算法的基本操作: 1.  哈希表(HashTable)简述   在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似 ...

  6. angularJS 入门知识

    模块:模块可以定义自己的控制器.服务.工厂类以及指令 模块可以依赖其他模块 模块两大常见错误: 定义模块的时候忘记第二个参数,变成使用模块而不是定义模块 使用模块的时候忘记引用依赖模块

  7. WPFの触发器详解

    例子1 简单触发器Triggers——满足简答的条件,触发 <Window x:Class="Styles.SimpleTriggers" xmlns="http: ...

  8. 五、Redis五种类型 - 字符串类型

    1.介绍: 字符串类型是Redis中最基本的数据类型,可以存储任何形式的字符串数据,最大容量是512MB. key 和 value 都是区分大小写的. 2.命令介绍 (1).赋值: set key v ...

  9. 第4篇创建harbor私有镜像库

        一.部署准备: 1.准备harbor软件包       在部署节点上:       2.挂载一个磁盘,专门存储harbor镜像和文件     3.进入到/etc/docker/harbor/目 ...

  10. LeetCode--Longest Consecutive Sequence(最长连续序列) Python

    题目描述: Longest Consecutive Sequence(最长连续序列) 中文: 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). 英文: Given ...