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, . ...
随机推荐
- 解决让刷新页面时不提示 "重试或取消”对话框
如果刷新一个已经提交过的页面时,系统总是会提示一个 "重试或取消”的对话框.,如果是一个普通的页面,好象也无所谓,有就有,大不了多点一下.但是当我们是在子窗体中刷新父窗体时,就显得有点多余了 ...
- 8条关于Web前端性能的优化建议
一般网站优化都是优化后台,如接口的响应时间.SQL优化.后台代码性能优化.服务器优化等.高并发情况下,对前端web优化也是非常重要的. 下面说说几种常见的优化措施. 1.HTML CSS JS位置 一 ...
- SpringBoot入门简介
SpringBoot诞生的背景 所有软件行业里面,如果要说商用体系,排在第一位的永远是java,因为java的体系丰富,支持度高,安全性也高 但是我们所有的开发者也不得不去忍受Java中的以下痛苦 举 ...
- sublime text 3安装Anaconda插件之后写python出现白框
sublime test 3安装anaconda插件之后写python代码会出现白框,这是应为anaconda自带了pep8语法检查, 有一些是语法错误,能够检查出来还是能有用的.但有一些不过是一些代 ...
- python 大小写转换函数
capitalize() 首字母大写,其余全部小写 upper() 全转换成大写 lower() 全转换成小写 title() 标题首字大写,如"i love python".t ...
- 62.Longest Valid Parentheses(最长的有效括号)
Level: Medium 题目描述: Given a string containing just the characters '(' and ')', find the length of ...
- 使用 lombok 简化代码
使用前的准备 1.Lombok 是一种 Java™ 实用工具,可用来帮助开发人员消除 Java 的冗长,尤其是对于简单的 Java 对象(POJO).它通过注解实现这一目的. <1>添加 ...
- elasticsearch 中的Multi Match Query
在Elasticsearch全文检索中,我们用的比较多的就是Multi Match Query,其支持对多个字段进行匹配.Elasticsearch支持5种类型的Multi Match,我们一起来深入 ...
- signal - 有效信号的清单
描述 (DESCRIPTION) 下面 列出 Linux 支持的 信号. 某些 信号 依赖于 体系结构(architecture). 首先, POSIX.1 描述了 下列 信号. 信号 值 动作 说明 ...
- Ansible --05 ansible jinja2
ansible jinja2 什么是jinjia2模板 jinjia2是Python的全功能模块引擎 Jinjia2与Ansible的关系 Ansible通常会使用jinjia2模板来修改被管理主机的 ...