CF 633 DIV2 C

题意:给你一个数组,你可以对数组里的任意元素进行如下操作:

在第X秒,你可以任意多个元素加上2^(x-1)  ,注意:你也可以一个都不选,即第X秒pass掉。

问你X取多少时可以使得数组是非递减的。要你求X的最小值。
思路:我们把2的次方写出来 1,2,4,8,16……很容易(其实一点也不容易)发现这些数可以组成所有正整数。再说细致一点,就是当x=n时,前x-1秒内的2^(x-1)可以组成1到2^x-1中的所有数。

这么一来我们就可以得出一个结论,如果a i  > a i+1  一定可以使a i+1 == a i 所以答案也就得出来了。

//author CN.TTDragon
#include<bits/stdc++.h>
typedef long long ll;
const ll mod=1e9+7;
const ll maxn=1e5+7;
const double pi=acos(-1);
using namespace std;
ll a[maxn]={0};
//快速幂,防止pow的各种谜之问题 ll qp(
int a,int b) { ll ret=1; while(b) { if(b&1) { ret=ret*a; } a=a*a; b>>=1; } return ret; }
int main() { int t; cin>>t; while(t--) { int n; cin>>n; memset(a,0,sizeof(a)); int mxsecond=0;//这个是最大的秒数 cin>>a[0]; int cnt=1;int jichu=0; for(int i=1;i<n;i++) { cin>>a[i]; jichu=a[i];//这里很重要的,如果a[i]>a[i-1],下面那个if就没意义了 cnt=1; while(a[i]<a[i-1]) { a[i]+=qp(2,cnt-1); mxsecond=max(cnt,mxsecond); cnt++; }
        //经过一通加法后,a[i]会>=a[i-1],但是我们前面提到了,这些2的次方的和是可以组成所有数的。
        //这里我们不妨把它们减去(注意这个减只是不加的意思,不是真正意义上的减),然它们相等,以减少下一个数的负担。
        //如果a[i]天生就比a[i-1]大,那我们是不能减的。
if(a[i]>a[i-1]&&jichu<a[i-1]) { a[i]=a[i-1]; } } /*for(int i=0;i<n;i++) { cout<<a[i]<<" "; }*/ //cout<<endl; cout<<mxsecond<<endl; } return 0; }

写在最后:

  第一次在DIV2中写出三道题,写完的时候超级开心~  来到了青名,希望自己以后再接再厉。能早日AK比赛~
  这篇文章就当一个纪念吧~
  关注了很多大佬,希望能把每次不会的题补好吧~拼命不咕~
PS :数论TAG是乱加的~

posted @ 2020-04-13 22:15  摸鱼自动机  阅读(136)  评论(0)    收藏  举报