题干:

Mr. Frog has n sticks, whose lengths are 1,2, 3⋯⋯n respectively. Wallice is a bad man, so he does not want Mr. Frog to form a triangle with three of the sticks here. He decides to steal some sticks! Output the minimal number of sticks he should steal so that Mr. Frog cannot form a triangle with 
any three of the remaining sticks.

Input

The first line contains only one integer T (T≤20T≤20), which indicates the number of test cases. 

For each test case, there is only one line describing the given integer n (1≤n≤201≤n≤20).

Output

For each test case, output one line “Case #x: y”, where x is the case number (starting from 1), y is the minimal number of sticks Wallice should steal.

Sample Input


3 4 5 6

Sample Output


Case #1: 1 Case #2: 1 Case #3: 2

解题报告:

    看网上的题解都说是打表,那怎么打的表啊?手推?万一不正确呢?有点侥幸啊。。其实这题也可以搜索来找答案,但是还有更好的方法,比如用set,也是0ms过,我看好多打表的都是15ms,不知道是什么情况。

AC代码:

#include<bits/stdc++.h>

using namespace std;

int main()
{
int t,n;
int iCase = 0;
scanf("%d",&t);
while(t--) {
scanf("%d",&n);
printf("Case #%d: ",++iCase);
if(n <= 3) {
printf("0\n");continue;
}
int ans = 0;
set<int> st;
for(int i = 1; i<=n; i++) st.insert(i);
set<int>::iterator it,itt,ittt,qq;

int flag = 1;
while(flag) {
qq=st.end();
qq--;qq--;
for(it = st.begin(); it!=qq; ++it) {
itt=++it;
--it;
ittt=++itt;
--itt;
if(*it + *itt > *ittt) {
st.erase(ittt);ans++;break;
}
++it;
if(it == qq) flag=0;
--it;
}

}
printf("%d\n",ans);
}
return 0 ;
}

总结:

    刚开始写的时候错误还是比较多的,比如for遍历的时候it != st.end(),但是这题不行,因为itt和ittt就越界了。。所以这题qq迭代器就是记录一下st.end()往前两个是多少。还有一个坑点就是需要实时计算qq的值,因为你有erase操作,所以st.end()就在变,所以qq也要跟着变才对。再就是n<=3的时候要特判,输出格式的空格要注意。


还有一个类似的题目在别的题解上看到了这里粘贴一下:

切金条

一根金条长31厘米,如果把它切成数段,使其中的一段或几段能够接成长为1到31中任何整数的金条,请问要切几次?

题解:第一反应是斐波那契数列1 2 3 5 8 12,切5刀,结果错了,这道题应该用二进制做。123是不需要3的,因为12可以构成3,所以124是更好的选择。

这两道题好像,但是这是两道题,一定要仔细区分开。

1 2 4 8 16,和正好31,切4刀,答案是4。