Codeforces Round #863 (Div. 3)
题目描述
题意介绍
给我们一个高为f[n]
,宽为f[n + 1]
的矩形,然后我们需要把这个矩形分割成n + 1个正方形。它要求必须要有两个边长为1的正方形,并且其余正方形的边长必须为斐波那契数列的值。问我们是否可以完成分割。
思路介绍
我一开始是完全没思路的,因为没有发现斐波那契的数学性质:
图片来自为知乎上一位大佬的文章
知道了上述的性质后就好想多了,划分的正方形边长分别刚好是0~n的斐波那契的每一个值,而且给我们说了一个f[0]
位置,那我们就可以贪心的考虑最大的边长该放哪
- 最大的首先放在横向方向上,然后我们再把剩余的矩形进行翻转,变成宽比较大的那种情况
- 就这样重复下去即可
代码实现
非递归形式
#include<iostream>
#include<cstring>
using namespace std;
const int N = 45;
int Q, n, x, y;
int f[N];
int main(){
f[0] = 1, f[1] = 1;
for(int i = 2; i < N; i ++)
f[i] = f[i - 1] + f[i - 2];
// cout << f[N - 1] << endl;
cin >> Q;
while(Q --){
cin >> n >> x >> y;
for (int i = n; i >= 1; i--) {
if (((n - i) & 1)==0) {
if (y > f[i]) y -= f[i];
}
else {
if (x > f[i]) x -= f[i];
}
}
if(x == 1 && y == 1) puts("YES");
else puts("NO");
}
return 0;
}
递归形式
#include<iostream>
#include<cstring>
using namespace std;
const int N = 45;
int Q, n, x, y;
int f[N];
bool dfs(int n, int x, int y){
if(n == 0) return true;
if(y > f[n]) return dfs(n - 1, f[n + 1] - y + 1, x);
else if(y <= f[n - 1]) return dfs(n - 1, y, x);
return false;
}
int main(){
f[0] = 1, f[1] = 1;
for(int i = 2; i < N; i ++)
f[i] = f[i - 1] + f[i - 2];
// cout << f[N - 1] << endl;
cin >> Q;
while(Q --){
cin >> n >> x >> y;
if(dfs(n, x, y)) puts("YES");
else puts("NO");
}
return 0;
}
参考思路
https://zhuanlan.zhihu.com/p/619641668
https://zhuanlan.zhihu.com/p/619618750