codeforces 1338A - Powered Addition (二进制表示)

题目大意:

现在有一个数列an,每次,我们可以进行无数次操作,每次可以选择任意的数字往其中加2^x,其中x为第x次操作。问我们,为了使得最终数列满足单调递增,我们最少需要做多少次的操作。

n<=1e5

解题思路:

首先,我们从左往右看数列,假如一个数比前面的数字要大,那么很明显地,我们不应该对这个数字再增加(否则给后面的数字带来负担),当比前面的数字ai-1要小的时候,我们需要思考这一个数字需要加多少。那么,我们发现当前数字最好是加到和ai-1一样大,为什么呢?因为这个差值的二进制表示的位数等同于需要我们用到操作数,那么我们肯定想这个差值要尽可能地小从而所占的位数不多,毕竟我假如只用0b'100来表示差值(3次操作)就足够了没必要用0b'1000(4次操作)来表示!最后答案就是我们操作数的最大值。

#include <bits/stdc++.h>
#define int long long 
using namespace std;
int32_t main(){
    int cas;cin>>cas;
    while(cas--){
        int n;cin>>n;
        vector<int> arrmv(n+1);
        for(int i=1;i<=n;i++)cin>>arrmv[i];
        
        int ans = 0;
        for(int i=2;i<=n;i++){
            if(arrmv[i]>arrmv[i-1])continue;
            int no = arrmv[i-1]-arrmv[i] ;
            int cnt = 0;
            while(no){
                cnt++;
                no>>=1;
            }
            arrmv[i] = arrmv[i-1];
            ans = max(ans, cnt);
        }
        cout<<ans<<endl;
    }
	return 0;
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值