csdn编程练习之-3+1

题目详情:

有一个数列,所有的数都是非负整数,你可以进行如下方式进行一次操作(注意一次完整的操作必须先后完成如下两个步骤):

(1) 任选一个不小于3的数,把它减少3。

(2) 任选一个数把它增加1。

请问,最多能够操作多少次?

输入格式:

多组数据,每组数据第一行是一个正整数n,表示数列中数的个数。(1<=n<=20000)

第二行包含n个空格分隔的非负整数,每个整数不超过1000000。

输出格式:

对每组数据输出一行,表示最多可以进行的操作次数。


输入:

1

10

2

10 11

输出:

4

10



详解:

先试个简单的例子:输入为2  

4 5    

则可进行的操作如下:(其他操作方式的最多次数也是一样的)

{1,5,2,5},{2,2,2,3},{2,0,3,0},{0,0,1,0}最多共4次操作。可以看出每有一个大于三的数就可以操作一次,除此之外,通过加1之后大于等于三的数也可以进行一次操作。推广到n则可以这样解:

输入的n个数,我们都可以把这n个数分解成n1个1,n2个2,n3个3。则至少可以进行n3次操作,通过加1可进行的操作数为:(这时候问题可以看成是逢三进一的问题,类似于每三个啤酒瓶能换一瓶啤酒,问有n个啤酒瓶最多能换多少瓶酒的问题)。剩下的数为s=(n1+2*n2+n3),接下来是解决逢三进一的问题,设操作数为t。当s=1,或2时,t=0,当s=3或4时,t=1;以此类推,得到这个数列的通项公式为t=s%2? (s-1)/2 : (s-2)/2;  这t次操作是后面的通过加1可得到的操作数,加上原来最少能进行的操作数即为所要求的次数。

再看看 2   4 5 这个例子。

4 和5 可分成 2个3 和1 个1 和1 个2。即n1=1;n2=1;n3=2;s=(1+2*1+2)=5;  t=(5-1)/2=2.   则总操作数为n3+t=4;


代码如下:

#include<iostream>
using namespace std;
int main()
{
int i,n;
while(scanf("%d",&n)!=EOF){
__int64 n1=0,n2=0,n3=0,step=0,sum;
for(i=0;i<n;i++){//把这n个数全部分解成n1个1,n2个2,n3个3;
__int64 num;
scanf("%I64d",&num);
n3+=num/3;
if(num%3==2)
n2++;
if(num%3==1)
n1++;
}
sum=n1+2*n2+n3;//这步可理解为所有“可以加的1”,一共有n1+2*n2+n3个1;
step=n3 + sum%2 ? (sum-1)/2 : (sum-2)/2;//初始步数加上增加的步数;
printf("%I64d\n",step);
}
return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值