题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1996
题目描述:问三个柱子上放N个盘子,一共可能有多少种组合?(可以有柱子不放,放的时候依然满足下面盘子比上面盘子大)
解题思路:
对于放N个盘子,ans [ N ] = 3 + 6 * f ( N ) +6 * g ( N )
这三项依次代表这N个盘子分成一堆,两堆,三堆时有多少种可能。排列组合什么的不多解释、
f 函数代表分两堆这个过程中有多少种可能。
g 函数代表分三堆这个过程中有多少种可能。
公式在代码里,意思是,最后新放进去的这个盘子肯定是最小的,可以放在三堆任意一堆堆顶构成新组合,所以是放他之前的所有可能数乘以 3 ,再加上它自成一堆,其他盘子分成两堆的可能数量。
AC代码:
#include <iostream>
using namespace std;
typedef long long ll;
ll ans[40];
ll f(ll x)
{
if(x<2)
return 0;
if(x==2)
return 1;
return 2*f(x-1)+1;
}
ll g(ll x)
{
if(x<3)
return 0;
if(x==3)
return 1;
return 3*g(x-1)+f(x-1);
}
int main()
{
int T,N,i;
for(i=1;i<30;i++)
{
ans[i]=3+6*f(i)+6*g(i);
//cout<<ans[i]<<endl;
}
while(cin>>T)
{
while(T--)
{
cin>>N;
cout<<ans[N]<<endl;
}
}
return 0;
}
AC截图: