高校俱乐部(-3+1)题解

最近好久没做高校俱乐部了,今天杭电在比赛,又不想刷其他了,就随便看看。

看到一个三星题目,-3+1,第一个反应就是3n+1啦,之后暴力什么的涌现眼前。

来看题目

-3+1

题目详情:

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

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

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

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

输入格式:

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

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

输出格式:

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



答题说明:

输入样例

1

10

2

10 11

输出样例:

4

10

水题一道,我都懒得解释了……

思路:每次减三都可以得到加一,所以输入的时候,我就直接mod3,用sum来记下可加的数目tmp/3,之后分别记下mod掉剩余的0,1,2 三个数,其实0不用记的,但是效率差不多,直接就用数组a来记下0,1,2的个数啦。

之后问题就转化为将sum分配给0,1,2,当然这个过程sum会先减后加……

做法就是贪心咯……先把二填完,再填一……再填零……

上代码,更容易理解。

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
long long a[5];

int main(){
    long long n,i,sum,cnt,tmp;


    while(cin>>n){

      sum=0LL;
      cnt=0LL;
       a[1]=a[2]=0;
      for(i=0;i<n;i++)
     {
        cin>>tmp;
        sum+=tmp/3;  //可分配的1
        cnt+=tmp/3;  //操作次数
        tmp%=3;
        a[tmp]++;   //统计

     }

     if(sum)//如果没有可分配的就不能烧啊!

     cnt+=a[2];//a[2]直接全部花掉,因为消耗完马上又有了。

    while(1){ //分配1的

       tmp=min( sum>>1 ,a[1]);
       cnt+=tmp;
       sum-=tmp;
       a[1]-=tmp;
       if(sum<1||a[1]<1)break;

    }
    while(1){  //分配0的

       tmp=sum/3;
       sum%=3;
       sum+=tmp;
       cnt+=tmp;
       if(sum<=2) break;
    }
     cout<<cnt<<endl;


    }

    return 0;

}

如果你觉得我的做法不给力,或者不明白,可以评论,看到即回复。

你可能感兴趣的:(题解)