0
点赞
收藏
分享

微信扫一扫

hpuoj-1048-QAQ的纸币问题(二)【思维】


题目链接:​​点击打开链接​​


[思维]


时间限制: 1 Sec   内存限制: 128 MB

提交: 18  

解决: 7

[​提交​​][​状态​​][​讨论版​​]


题目描述


这天无聊的QAQ又在研究纸币的组合问题,QAQ发现只需要1、2、7 1、2、7三种面值就可以通过加法和减法组成1−10 1−10的所有数字。如:
1=1 1=1
2=2 2=2
3=1+2 3=1+2
4=7−1−2 4=7−1−2
5=7−2 5=7−2
6=7−1 6=7−1
7=7 7=7
8=1+7 8=1+7
9=2+7 9=2+7
10=1+2+7 10=1+2+7
QAQ想知道最少需要多少种不同的面值就可以构成从1−N 1−N的所有数字,由于N N很大,就请了你这个BestCoder来帮他。
PS:构成每一个数字,同种面值最多使用一张。


输入


第一行输入一个整数T T,代表有T T组测试数据。

每组数据输入一个整数N N,代表上面提到的信息。



注:1<=T<=666666,1<=N<=666666 1<=T<=666666,1<=N<=666666。


输出


输出一个整数代表最后的结果。


样例输入

3
1
10
666666

样例输出

1
3
13



思路:

还可以增加难度的 —— 输出任意一种合法的选择方案。

如果理解了下面的过程,也是很简单的。

考虑一个最优策略:

第一次选择1,可以构造出数字1。

第二次选择3,可以构造数1~4所有数字。

第三次选择5,可以构造出1~9所有数字。

第四次选择10,可以构造出1~19所有数字。

……


发现:

选择 i 张纸币构造的最优解 = 选择 i - 1 张纸币构造的最优解的 2 倍 + 1。

预处理一下结果,每次查询时间复杂度 O(1)。预处理时间复杂度是 O(666666*2)。

心细的同学会发现选择的纸币也是有规律的

1,3,5,10,20,40,80,160,320,640......

所以说输出任意一种合法方案,也是很简单的。

#include<cstdio>
#include<algorithm>
using namespace std;
int n;
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
int sum=0,ans=0;
while(sum<n)
{
sum=sum+sum*2+1;
ans++;
}
printf("%d\n",ans);
}
return 0;
}


举报

相关推荐

0 条评论