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, . ...
随机推荐
- GET和POST区别及缓存问题
2.就是get和post区别的缓存问题. 首先要了解什么是缓存. HTTP缓存的基本目的就是使应用执行的更快,更易扩展,但是HTTP缓存通常只适用于idempotent request(可以理解为查询 ...
- 进程管理工具-Supervisord 使用
简介 Supervisor 是一个用 Python 写的进程管理工具,可以很方便的用来在 UNIX-like 系统(不支持 Windows)下启动.重启(自动重启程序).关闭进程(不仅仅是 Pytho ...
- PAT_A1077#Kuchiguse
Source: PAT A1077 Kuchiguse (20 分) Description: The Japanese language is notorious for its sentence ...
- ubuntu snap 包管理器
基本使用 snap find $package snap install $package [--channel=beta] snap list snap refresh $package [--ch ...
- Linux安装Apache报错:Cannot find a valid baseurl for repo: base/7/x86_64解决方案
最近使用CentOS7学习,安装安装Apache时候,使用yum安装Apache报错:本文适合CentOS7和RHEL7 # yum install httpd 出现:cannot find a va ...
- Java开发用H2数据库
#JPA Configuration:#spring.jpa.database=MySQLspring.datasource.url=jdbc:h2:mem:jpaspring.datasource. ...
- Nuget--基础连接已经关闭
1.Nuget---基础连接已经关闭: 未能为 SSL/TLS 安全通道建立信任关系 修改一下 Package Source 改为 http://packages.nuget.org 2.Nuget- ...
- PascalCase & camelCase & kebabCase
帕斯卡拼写法( 也叫大骆驼拼写法),一种计算机编程中的变量命名方法.它主要的特点是将描述变量作用所有单词的首字母大写,然后直接连接起来,单词之间没有连接符.比如: Age LastName Winte ...
- java nio socket使用示例
这个示例,实现一个简单的C/S,客户端向服务器端发送消息,服务器将收到的消息打印到控制台,并将该消息返回给客户端,客户端再打印到控制台.现实的应用中需要定义发送数据使用的协议,以帮助服务器解析消息.本 ...
- ORA-20782: Creating GGS_DDL_RULES
在11g数据库上安装goldengate,运行@ddl_setup.sql时有如下错误 ERROR at line 1: ORA-20782: Creating GGS_DDL_RULES table ...