
输入样例:
5
3
14
15
24
1
 
输出样例:
1
2
1
3
0
 
思路分析:
首先搭每个金字塔所需的扑克牌数并不会由n决定,所以我首先想到打表。抱着信心尝试一番之后
 

 既然文件太大提交不了,那我们就放弃:,怎么可能,下面我们来简单的计算一波,打表时间复杂度O(n),二分时间复杂度O(log n),所以打表+二分,时间复杂度OK。
 所以这一题的思路就是:把打表程序放在主程序里,用二分查找搭成最大金字塔所需扑克牌数量,
 再通过递归解决。
 既然要打表 (其实叫预处理) 那就先分析一下金字塔的规律 (如下图) :
 
总结规律:每次差增加3
 接着用二分查找出离n最近的金字塔,然后减去那个数在递归查找剩下的,知道小于2为止,因为最小的金字塔要2张扑克牌。
代码:
#include<iostream>
using namespace std;
int a[25850];//预处理数组 
int t,n;//由题意 
int ans=0;//记录答案 
void dg(int x){
	if(x<2){
		return;
	}//递归终止条件 
	int l=0,r=25850,mid;//r=25850是打表测出来的,在1e9内有25820种不同的金字塔结果,开大一点到25850 
	while(l<r){//二分 
		mid=(l+r+1)/2;
		if(a[mid]>x){
			r=mid-1;
		}else{
			l=mid;
		}
	}//找不大于x的最大值下标 
	ans+=1;//答案加一 
	dg(x-a[l]);//剩下的继续找 
	return;
}
int main(){
	int cnt=0/*所需扑克牌张数*/,tmp=2/*差值*/,idx=-1;//a数组下标 
	while(cnt<=1000000000){ 
		cnt+=tmp;
		tmp+=3;//差值加3 
		idx+=1;//下标加一 
		a[idx]=cnt;
	}//在输入前预处理(打表) 
	cin>>t;
	while(t--){//t次询问 
		ans=0;//答案初始化 
		cin>>n;
		dg(n);//递归调用 
		cout<<ans<<endl;
	}
	return 0;
}
 
下一篇:可可口乐






![golang+layui提升界面美化度--[推荐]](https://img-blog.csdnimg.cn/09668686a29d4895be92279c44b540ab.png)











