Gym 102082B : Arithmetic Progressions
题目大意:给你一个长度为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的更多相关文章
- [Educational Codeforces Round 16]D. Two Arithmetic Progressions
[Educational Codeforces Round 16]D. Two Arithmetic Progressions 试题描述 You are given two arithmetic pr ...
- 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 ...
- 洛谷P1214 [USACO1.4]等差数列 Arithmetic Progressions
P1214 [USACO1.4]等差数列 Arithmetic Progressions• o 156通过o 463提交• 题目提供者该用户不存在• 标签USACO• 难度普及+/提高 提交 讨论 题 ...
- POJ 3006 Dirichlet's Theorem on Arithmetic Progressions (素数)
Dirichlet's Theorem on Arithmetic Progressions Time Limit: 1000MS Memory Limit: 65536K Total Submi ...
- poj 3006 Dirichlet's Theorem on Arithmetic Progressions【素数问题】
题目地址:http://poj.org/problem?id=3006 刷了好多水题,来找回状态...... Dirichlet's Theorem on Arithmetic Progression ...
- (素数求解)I - Dirichlet's Theorem on Arithmetic Progressions(1.5.5)
Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit cid=1006#sta ...
- USACO 1.4 Arithmetic Progressions
Arithmetic Progressions An arithmetic progression is a sequence of the form a, a+b, a+2b, ..., a+nb ...
- Educational Codeforces Round 16 D. Two Arithmetic Progressions (不互质中国剩余定理)
Two Arithmetic Progressions 题目链接: http://codeforces.com/contest/710/problem/D Description You are gi ...
- 等差数列Arithmetic Progressions题解(USACO1.4)
Arithmetic Progressions USACO1.4 An arithmetic progression is a sequence of the form a, a+b, a+2b, . ...
随机推荐
- 用 Flask 来写个轻博客 (19) — 以 Bcrypt 密文存储账户信息与实现用户登陆表单
目录 目录 前文列表 修改 User Model Flask Bcrypt 将 Bcrypt 应用到 User Model 中 创建登陆表单 前文列表 用 Flask 来写个轻博客 (1) - 创建项 ...
- COALESCE 函数作用
用途. 将空值替换成其他值 返回第一个非空值. 任意一个不为空的值.比较有用.
- Android深度探索-卷1第一章心得体会
本章介绍了安卓系统移植与驱动开发的概述,安卓的系统架构有四层:1 Linux内核,2 c/c++代码库, 3 Android SDK API, 4 应用程序 在读的过程中看到了专业名词,查了查,长点 ...
- python使用消息队列RabbitMq(入门)
windows平台开发和使用 安装 安装Erlang:https://pan.baidu.com/s/1QcZDaI205uaue7mMWh5cSA 安装RabbitMQ:https://pan.ba ...
- 哈希算法和字典类的定义,DataSet中数据遍历的几种方法
哈希算法的基本操作: 1. 哈希表(HashTable)简述 在.NET Framework中,Hashtable是System.Collections命名空间提供的一个容器,用于处理和表现类似 ...
- angularJS 入门知识
模块:模块可以定义自己的控制器.服务.工厂类以及指令 模块可以依赖其他模块 模块两大常见错误: 定义模块的时候忘记第二个参数,变成使用模块而不是定义模块 使用模块的时候忘记引用依赖模块
- WPFの触发器详解
例子1 简单触发器Triggers——满足简答的条件,触发 <Window x:Class="Styles.SimpleTriggers" xmlns="http: ...
- 五、Redis五种类型 - 字符串类型
1.介绍: 字符串类型是Redis中最基本的数据类型,可以存储任何形式的字符串数据,最大容量是512MB. key 和 value 都是区分大小写的. 2.命令介绍 (1).赋值: set key v ...
- 第4篇创建harbor私有镜像库
一.部署准备: 1.准备harbor软件包 在部署节点上: 2.挂载一个磁盘,专门存储harbor镜像和文件 3.进入到/etc/docker/harbor/目 ...
- LeetCode--Longest Consecutive Sequence(最长连续序列) Python
题目描述: Longest Consecutive Sequence(最长连续序列) 中文: 给定一个未排序的整数数组,找出最长连续序列的长度. 要求算法的时间复杂度为 O(n). 英文: Given ...