Cut down integers (thinking + greedy)

https://ac.nowcoder.com/acm/contest/11163/C


The idea is very good.. But the bug has been adjusted for a long time.

Backward is greedy, the current number can take at most, and at least 1 should be taken for each number in front. The number is log, up to 30, and the number of times is up to 30. Violence is fine.

It is mainly about the code processing. First, first take -1 for each part that needs to be taken to prevent some boundary problems. Then take it greedy.

#include<iostream>
#include<vector>
#include<queue>
#include<cstring>
#include<cmath>
#include<map>
#include<set>
#include<cstdio>
#include<algorithm>
#define debug(a) cout<<#a<<"="<<a<<endl;
using namespace std;
const int maxn=50;
typedef long long LL;
inline LL read(){LL x=0,f=1;char ch=getchar();	while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
return x*f;}
LL p[maxn];
int main(void)
{
  LL t;t=read();
  p[0]=1;
  for(LL i=1;i<=40;i++) p[i]=p[i-1]*2;
  while(t--){
    LL H=read();
    if(H==2){
        printf("2\n");
        continue;
    }
    LL ans=1;
    H--;
    for(LL i=30;i>=0;i--){
        if(p[i]>H) continue;
        LL res=0;
        LL temp=H;
        LL cnt=0;

        for(LL j=1;j<=30;j++){///枚举次数
            if(temp-p[i]*j>=(1LL<<i)-1-1 ){

                cnt=max(cnt,j);

            }
            else{
                break;
            }
        }

        if(cnt==0) continue;

        res+=cnt;
        temp-=p[i]*cnt;

        for(LL j=i-1;j>=1;j--){
            temp-=p[j]*1;
            res++;
        }

        for(LL j=i-1;j>=0;j--){
            if(temp>0&&temp>=p[j]){
                res+=temp/p[j],temp%=p[j];
            }
        }
        ans+=res;
        break;
    }
    printf("%lld\n",ans);
  }
return 0;
}

 

Guess you like

Origin blog.csdn.net/zstuyyyyccccbbbb/article/details/115037584