题解:CF633D Fibonacci-ish

涉及知识点:枚举,STL

题目大意

给你一个序列,让你选出一些元素,使其构成 fibonacccccci 数列,求数列的最大长度。

解题思路

定义一个桶,\(mp_i\) 代表 \(i\) 这个数在输入序列当中出现的次数。

由于 \(n \le 1000\),所以可以直接暴力枚举 fibonacccccci 数列的前两个数。

前两个数固定了,这个序列的所有数字都固定了,只需要判断当前序列的下一个数字可不可以组合出来。

map<int, int> hh;
int cnt = 2;
int now1 = a[i];
int now2 = a[j];
hh[now1]++, hh[now2]++;
while (hh[now1 + now2] < mp[now1 + now2]) {
  int t = now1;
  now1 = now2;
  now2 = t + now2;
  hh[now2]++;
  cnt++;
}

再来说一下剪枝。

  1. 如果序列里包含 \(0\),先把 \(ans\) 初始化成 \(0\) 的个数,这样就可以防止枚举起点的多余计算。
  2. 如果序列包含两个及以上个 \(0\),需要在枚举前两个数时特判,因为起始两个 \(0\) 的序列全是 \(0\),会在第 \(1\) 种剪枝当中直接计算出来最优解。
  3. 如果前一个序列的第 \(1\) 个数和这个序列的第 \(1\) 个数相同,说明两个序列是完全一样的,直接跳过当前序列,计算下一个序列。

最后,统计每个序列长度,取最大值即可。

代码

#include <bits/stdc++.h>
#define int long long
#define endl '\n'
#define il inline
using namespace std;

const int N = 1000 + 10;

int n, a[N];
map<int, int> mp;
int ans;
vector<int> v;

il void Init() {
	cin >> n;
	for (int i = 1; i <= n; i ++ ) cin >> a[i];
}

il void Solve() {
	for (int i = 1; i <= n; i ++ ) mp[a[i]]++;//统计数字出现个数
	ans = max(ans, mp[0]);//剪枝1
	sort(a + 1, a + n + 1);
	for (int i = 1; i <= n; i ++ )
		for (int j = 1; j <= n; j ++ ) {
			if (i == j) continue;//起始不能为同一个位置的数
			if (a[i] == 0 && a[j] == 0) continue;//剪枝2
			if (i > 1 && a[i - 1] == a[i]) break;//剪枝3
			map<int, int> hh;//统计当前序列数字出现的个数
			int cnt = 2;
			int now1 = a[i];
			int now2 = a[j];
			hh[now1]++, hh[now2]++;
			while (hh[now1 + now2] < mp[now1 + now2]) {
				int t = now1;
				now1 = now2;
				now2 = t + now2;
				hh[now2]++;
				cnt++;//统计当前序列长度
			}
			ans = max(ans, cnt);//更新答案
		}
	cout << ans;
}

signed main() {
	ios::sync_with_stdio(false), cin.tie(0), cout.tie(0);
//	freopen("fibonacci.in", "r", stdin);
//	freopen("fibonacci.out", "w", stdout);
	int T = 1;
//	cin >> T;
	while (T--) {
		Init();
		Solve();
	}
}

通过记录

posted @ 2024-10-25 11:06  zla_2012  阅读(1)  评论(0编辑  收藏  举报