CF 633 D 离散化+二分查找+暴力(还是要多学习学习呀,挺好的题目)
2016-03-26 22:03
585 查看
http://codeforces.com/contest/633/problem/D
D. Fibonacci-ish
time limit per test
3 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output
Yash has recently learnt about the Fibonacci sequence and is very excited about it. He calls a sequence Fibonacci-ish if
the sequence consists of at least two elements
f0 and f1 are
arbitrary
fn + 2 = fn + 1 + fn for
all n ≥ 0.
You are given some sequence of integers a1, a2, ..., an.
Your task is rearrange elements of this sequence in such a way that its longest possible prefix is Fibonacci-ish sequence.
Input
The first line of the input contains a single integer n (2 ≤ n ≤ 1000) —
the length of the sequence ai.
The second line contains n integers a1, a2, ..., an (|ai| ≤ 109).
Output
Print the length of the longest possible Fibonacci-ish prefix of the given sequence after rearrangement.
Examples
input
output
input
output
Note
In the first sample, if we rearrange elements of the sequence as - 1, 2, 1,
the whole sequence ai would
be Fibonacci-ish.
In the second sample, the optimal way to rearrange elements is
,
,
,
, 28.
题目大意:
给一个数列。根据斐波那契数列的定义,得出最长的子序列。
思路:
因为是斐波那契数列,所以说如果前两项知道了,那么后面的数列就排好了。题解上面还有写到,因为斐波那契数列是接近于2的幂的,所以说最长的子序列是90.但是可能存在全都是0的子序列。所以要特别注意一下。
这道题想了好久还是不会做就看了一下别人的题解。
主要的方法是如下,首先,因为前两项是不知道的,所以要枚举所有的可能性,那就是n^2。然后因为要通过lower_bound来寻找函数(表示这点想到了,但是之前自己写的时候不知道为什么TLE了),所以说之前要排序。然后就是离散化了,将状态进行压缩,用b数组来记录一下a数组中重复的值。
还有一点就是用pos[]数组来保存值。
感觉这道题学到了一下几点
①可以用pos数组来储存下标。表示以前都是用pos来储存的,没怎么用过数组。
②离散化。减少重复的搜索和代码的长度,优化了。
③大牛代码中的思考条件都十分的全面,尤其是if中,一定要好好学习。
④最后别忘了使用过一次以后都加回来。
下面给出临摹的代码:(本人现在也只有这水平了。。。不过还是有点不一样的啦)
D. Fibonacci-ish
time limit per test
3 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output
Yash has recently learnt about the Fibonacci sequence and is very excited about it. He calls a sequence Fibonacci-ish if
the sequence consists of at least two elements
f0 and f1 are
arbitrary
fn + 2 = fn + 1 + fn for
all n ≥ 0.
You are given some sequence of integers a1, a2, ..., an.
Your task is rearrange elements of this sequence in such a way that its longest possible prefix is Fibonacci-ish sequence.
Input
The first line of the input contains a single integer n (2 ≤ n ≤ 1000) —
the length of the sequence ai.
The second line contains n integers a1, a2, ..., an (|ai| ≤ 109).
Output
Print the length of the longest possible Fibonacci-ish prefix of the given sequence after rearrangement.
Examples
input
3 1 2 -1
output
3
input
5 28 35 7 14 21
output
4
Note
In the first sample, if we rearrange elements of the sequence as - 1, 2, 1,
the whole sequence ai would
be Fibonacci-ish.
In the second sample, the optimal way to rearrange elements is
,
,
,
, 28.
题目大意:
给一个数列。根据斐波那契数列的定义,得出最长的子序列。
思路:
因为是斐波那契数列,所以说如果前两项知道了,那么后面的数列就排好了。题解上面还有写到,因为斐波那契数列是接近于2的幂的,所以说最长的子序列是90.但是可能存在全都是0的子序列。所以要特别注意一下。
这道题想了好久还是不会做就看了一下别人的题解。
主要的方法是如下,首先,因为前两项是不知道的,所以要枚举所有的可能性,那就是n^2。然后因为要通过lower_bound来寻找函数(表示这点想到了,但是之前自己写的时候不知道为什么TLE了),所以说之前要排序。然后就是离散化了,将状态进行压缩,用b数组来记录一下a数组中重复的值。
还有一点就是用pos[]数组来保存值。
感觉这道题学到了一下几点
①可以用pos数组来储存下标。表示以前都是用pos来储存的,没怎么用过数组。
②离散化。减少重复的搜索和代码的长度,优化了。
③大牛代码中的思考条件都十分的全面,尤其是if中,一定要好好学习。
④最后别忘了使用过一次以后都加回来。
下面给出临摹的代码:(本人现在也只有这水平了。。。不过还是有点不一样的啦)
#include<bits stdc="" h=""> using namespace std; const int maxn = 1000 + 5; int n, nn; int a[maxn], b[maxn]; int ans; void init(){ ans = 0; memset(a, 0, sizeof(a)); memset(b, 0, sizeof(b)); for (int i = 0; i < n; i++){ scanf("%d", a + i); ans += (a[i] == 0); } sort(a, a + n); ans = max(ans, 2); nn = 0; for (int i = 0; i < n; i++){ int t = i + 1; while (a[i] == a[t] && t < n) t++; a[nn] = a[i]; b[nn] = t - i; i = t - 1; nn++; } } void solve(){ int pos[maxn]; memset(pos, 0, sizeof(pos)); int f[maxn]; memset(f, 0, sizeof(f)); for (int i = 0; i < nn; i++){ f[0] = a[i]; b[i]--; for (int j = 0; j < nn; j++){ if (b[j] == 0 || (a[j] == 0 && a[i] == 0)){ continue; } f[1] = a[j]; b[j]--; for (int cnt = 2;; cnt++){ f[cnt] = f[cnt - 1] + f[cnt - 2]; pos[cnt] = lower_bound(a , a + nn, f[cnt]) - a; //不是单单就用pos,而是为了保存每一个的位置,使用pos[cnt] if (a[pos[cnt]] != f[cnt] || b[pos[cnt]] == 0 || pos[j] == nn){ while (cnt > 2){ cnt--;//顺序千万不能反了 b[pos[cnt]]++; } break; } ans = max(ans, cnt + 1); b[pos[cnt]]--; } b[j]++; } b[i]++; } printf("%d\n", ans); } int main(){ while (scanf("%d", &n) == 1){ init(); solve(); } return 0; } </bits>
相关文章推荐
- Hive UDF自定义函数编写小例子
- Atitit.反编译apk android源码以及防止反编译apk
- Atitit.反编译apk android源码以及防止反编译apk
- 高方差与高偏差学习笔记
- iPhone 和Android应用,特殊的链接:打电话,短信,email
- HDU 5651 xiaoxin juju needs help 水题一发
- Atitit。Cas机制 软件开发 编程语言 无锁机制 java c# php
- OC NSString字符串比较
- 第67课:Spark SQL下采用Java和Scala实现Join的案例综合实战(巩固前面学习的Spark SQL知识)
- HDOJ 1302 具体解释(简单模拟)
- Atitit。Cas机制 软件开发 编程语言 无锁机制 java c# php
- Atitit。Cas机制 软件开发 编程语言 无锁机制 java c# php
- HDU 5652 India and China Origins 并查集
- vim字符编码设置学习整理
- 正则表达式
- My First Cpp Programming
- 他们的CSS3 3D正方体
- JAVA方法声明中参数的那三个小数点
- POJ1611The Suspects
- Java网络编程(TCP协议-练习-上传文本文件)