1 条题解
-
0
考虑为什么先手必胜。
注意到后手永远无法改变石子的总个数,而只有石子个数为 时会出现一方输的情况。
那么也就是后手需要尽可能保证石子多,先手尽可能让石子少。
可以观察出这样一个过程,每一步先手选一个位置清空,后手把一个位置重新平分,这样对于每个堆所需要的次数是固定的。
那这题做完了吗?
注意到初始是先手先操作,而做完上述操作一轮后会变成后手先操作,而后手在已经平均的情况下操作是不优的。
而后手只有在操作 时会使得上述过程的次数 ,而且如果继续操作只会保持不变,所以现在先手需要最大化能让后手强制 的数量。
先手可以先操作若干次来让对手处于 的状态,而注意到如果当前总石子数是奇数,分成两部分后,后手也可以来回移动,所以要在偶数的情况下让后手选。
那么会发现 是一个很关键的状态,因为这样是先手不断选这个数的情况下最后一次偶数,而每次后手选到这个会使得 减少 。
这样问题就很明显了,用堆维护所有 ,先手每次会删去一个 ,后手每次可以给一个 减去 ,最后双方分别最小化/最大化 删去的 中 的数量(不能减到小于 )。
用堆维护,双方每次一定都选最大的那个数,时间复杂度 ,可以优化至线性。
i64 n,a[maxn]; i64 calc1(i64 x){ if(!x)return 0; return calc1(x/2)+1; } int main(){ // freopen("1.in","r",stdin); // freopen("1.out","w",stdout); n=read(); i64 s1=0,mn=1e9,Ans=0; priority_queue<i64>qwq; F(i,1,n){ a[i]=read();i64 k=__lg(a[i]); while(__builtin_popcount(a[i]+1)!=1) a[i]/=2,s1++; a[i]=__builtin_popcount(a[i]); s1+=a[i]+1; qwq.push(a[i]); if(!a[i])s1--; // printf("%lld\n",a[i]); } bool xo=0; while(qwq.size()){ i64 u=qwq.top();qwq.pop(); // cout<<u<<endl; if(xo==0); else{ if(u==1)s1--,xo=0; else qwq.push(u-1); } xo^=1; } printf("%lld\n",2*s1-1); return 0; }
- 1
信息
- ID
- 5763
- 时间
- 2000ms
- 内存
- 228MiB
- 难度
- (无)
- 标签
- 递交数
- 0
- 已通过
- 0
- 上传者