题解:P16993 [NWERC 2018] 倒霉下注 / Jinxed Betting
思路
显然最劣情况是 Julia 每场比赛都不加分,为了使它尽快被超越,所以其他人一定是能加分就加分。
以下将分数为最大值的人称为聪明人,其余人为普通人。
因为 Julia 不加分,所以肯定有一半的聪明人要和 Julia 选一样的队伍,也就是说只有另一半的聪明人可以加分。
但是普通人选择不受影响,所以他们可以加分。
假设当前有
讲了一大堆,有什么用呢?考虑先把
代码
#include<bits/stdc++.h>
#define int long long
#define For(i,j,k) for(int i=(int)j;i<=(int)k;i++)
#define Fro(i,j,k) for(int i=(int)j;i>=(int)k;i--)
#define Forr(i,j,k,l) for(int i=(int)j;i<=(int)k;i+=l)
#define Fror(i,j,k,l) for(int i=(int)j;i>=(int)k;i-=l)
#define debug1 cout<<"akioi\n";
#define debug2 For(i,1,n) cout<<a[i]<<" ";
#define pb push_back
#define file(x) freopen(x".in","r",stdin);freopen(x".out","w",stdout);
using namespace std;
typedef pair<int,int> pii;
const int N=1e5+10,mod=1e9+7,inf=1e18;
int n,M,cnt[N],len,sum,tot,p[N],a[N];
int calc(int x){//二进制下位数
int cnt=0;
while(x) cnt++,x>>=1;
return cnt;
}
signed main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n;
For(i,1,n) cin>>p[i];
sort(p+2,p+n+1,greater<>());
a[++len]=p[1],cnt[len]=1;
For(i,2,n){
if(i==2||p[i]!=p[i-1]) a[++len]=p[i],cnt[len]=1;//将相同分数的人变成一个人
else cnt[len]++;
}
if(a[2]==a[1]&&cnt[2]>1) return cout<<0,0;
M=a[2],tot=cnt[2];
For(i,3,len){
int c=M-a[i]-sum;//距离最大值还有几分
int z=calc(tot)-1;//一个周期内,聪明人加的分数
if(M+z*c>a[1]) break;
sum+=(z+1)*c,M+=z*c,tot+=cnt[i];//更新比赛数,最大值和最大值数量
}
int z=calc(tot)-1;
a[1]++;
if((a[1]-M)%z) cout<<sum+(a[1]-M)/z*(z+1)+(a[1]-M)%z-1;
else cout<<sum+(a[1]-M)/z*(z+1)+(a[1]-M)%z-2;
return 0;
}