题目描述
现在有一个大小n*1的收纳盒,我们手里有无数个大小为1*1和2*1的小方块,我们需要用这些方块填满收纳盒,请问我们有多少种不同的方法填满这个收纳盒
输入描述:第一行是样例数T 第2到2+T-1行每行有一个整数n(n<=80),描述每个样例中的n。 输出描述:
对于每个样例输出对应的方法数。 示例1 输入
3 1 2 4 输出
1 2 5 说明
n=4,有五种方法 1:1 1 1 1
3:1 2 1
4:1 1 2
5:2 21 2 3 4 5 6
备注:
对于100%的数据, 0 < T < 80; 0 < n <= 80。
这道题和走n阶楼梯是一样的, 使用递推的方法. 答案就是斐波那契数列.
如何理解?
当走第n阶楼梯时, 我们可以知道从上一步到这一步有两种可能, 一是从n-1阶楼梯跨了一步来的, 另一种可能是从n-2阶楼梯跨了2步来的. 所以方法为Fn-1 + Fn-2. 知道1, 2阶楼梯的方法即可递推得到.
#include <iostream>
using namespace std;
int main( )
{
int t, n;
cin >> t;
while( t-- ) {
cin >> n;
long long a[3] = {3, 1, 2};
for( int i = 4; i <= n; ++i )
{
a[i%3] = a[(i-1)%3] + a[(i-2)%3];
}
cout << a[n%3] << endl;
}
}
总结: 要善于观察和推导. 我在思考的过程中想了用递归的方法, 每次走一步或两步, 结果空间太大了. 其实其中的思想就是递推.
还想了用数学里面的组合方法, 枚举所有可能的1步或两步情况, 再计算每一种情况的情况.
垃圾代码如下:
#include <iostream>
#include <algorithm>
using namespace std;
int main( )
{
int t, n;
cin >> t;
while( t-- ) {
cin >> n;
unsigned long long ans = 0;
for( int i=0;i<=n; ++i) {
if(n%2==0 && i%2==1) continue;
if(n%2==1 && i%2==0) continue;
unsigned long long all = i + (n-i)/2;
unsigned long long tmp = 1, temp = 1;
int k = min((unsigned long long)i, all-i);
for( int j = all; j>=all-k+1; --j ) {
tmp *= j;
}
for( int j = 1; j<=k; ++j) {
temp *= j;
}
ans += tmp/temp;
}
cout << ans << endl;
}
}
通过了50%的样例.
大概是因为这种方法得到的中间量可能超范围.