Hyper Box
思路:
是斐波那契数的不用管,不是斐波那契数的,需要把它拆开成多个斐波那契数,找到输入数字的小于它的最大的斐波那契数,减去它,再找减去后的数字的小于它的最大的斐波那契数,减去它,不断循环,直到减去的数字本身是个斐波那契数为止。
因为下面的证明要多次用到“小于那个非斐波那契数的最大的斐波那契数”,姑且先记为A。
从A开始减的道理是,一个非斐波那契数,最少需要两个斐波那契数相加才能组成。假如一个非斐波那契数,可以由两个斐波那契数相加组成,如果这两个数不包括A,那么这两个数相加一定小于A,是不可行解。
假如一个非斐波那契数,最少由n个斐波那契数相加组成,那么这些数一定不相邻,否则n就不是最少的,假设这些斐波那契数的下标可以标记为,
a
1
a_1
a1,
a
2
a_2
a2,
a
3
a_3
a3…
a
n
a_n
an,并且不包括A的下标,把A的下标记为
a
0
a_0
a0。
f
i
b
[
a
1
]
+
f
i
b
[
a
2
]
<
f
i
b
[
a
3
−
1
]
fib[a_1]+fib[a_2]<fib[a_3-1]
fib[a1]+fib[a2]<fib[a3−1]
f
i
b
[
a
1
]
+
f
i
b
[
a
2
]
+
.
.
.
.
.
.
f
i
b
[
a
n
]
<
f
i
b
[
a
n
−
1
]
+
f
i
b
[
a
n
]
fib[a_1]+fib[a_2]+......fib[a_n]<fib[a_n-1]+fib[a_n]
fib[a1]+fib[a2]+......fib[an]<fib[an−1]+fib[an]
f
i
b
[
a
n
−
1
]
+
f
i
b
[
a
n
]
≤
f
i
b
[
a
0
]
fib[a_n-1]+fib[a_n]≤fib[a_0]
fib[an−1]+fib[an]≤fib[a0]
f
i
b
[
a
1
]
+
f
i
b
[
a
2
]
+
.
.
.
.
.
.
f
i
b
[
a
n
]
<
f
i
b
[
a
0
]
fib[a_1]+fib[a_2]+......fib[a_n]<fib[a_0]
fib[a1]+fib[a2]+......fib[an]<fib[a0]
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+7;
int T,n;
ll fib[51];
ll arr[20];
map<ll,int> f;
void getfib(){
fib[0]=1;
fib[1]=2;
for(int i=2;i<=50;i++){
fib[i]=fib[i-1]+fib[i-2];
}
for(int i=0;i<=50;i++){
f[fib[i]]=i;
}
}
ll fun(ll num){
int ans=1;
while (f.find(num) == f.end())
{
int cc;
for (int i = 0; i < 51; i++)
{
if (num < fib[i])
{
cc = i;
break;
}
}
num -= fib[cc - 1];
ans++;
}
return ans;
}
int main(){
ios::sync_with_stdio;
getfib();
cin>>T;
for(int i=1;i<=T;i++){
cin>>n;
for(int j=0;j<n;j++){
cin>>arr[j];
}
ll ans=1;
for(int j=0;j<n;j++){
ans*=fun(arr[j]);
}
cout<<"Case "<<i<<": "<<ans<<endl;
}
return 0;
}