- 你的做法模拟到了所有社团都至少分到了1个格子,用double实现会有精度问题,既然可以避免就避免吧
- 题解则观察到了分界值和划分出的席位数之间良好的单调关系,采用二分的方法求解
- 但这种做法有严重的精度问题,根源在于分界值趋近于0,可以通过取log或者拆分整数和小数的方法优化
点击查看代码
#include <bits/stdc++.h>
using namespace std;
long long w[100005],cnt[100005];
long long ans[100005],u[100005];
struct t1
{
long long cnt,w;
long long i;
bool pd;
};
auto cmpt=[](t1 a,t1 b)
{
if(a.w*(1<<b.cnt)!=b.w*(1<<a.cnt))
{
return a.w*(1<<b.cnt)<b.w*(1<<a.cnt);
}
if(a.pd^b.pd)
{
return b.pd==true;
}
if(a.w!=b.w)
{
return a.w<b.w;
}
return a.i>b.i;
};
priority_queue<t1,vector<t1>,decltype(cmpt)>q(cmpt);
bool cmp(long long a,long long b)
{
if(w[a]*(1<<cnt[b])!=w[b]*(1<<cnt[a]))
{
return w[a]*(1<<cnt[b])>w[b]*(1<<cnt[a]);
}
if(w[a]!=w[b])
{
return w[a]>w[b];
}
return a<b;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(0);
long long n,h;
cin>>n>>h;
for(long long i=1;i<=n;i++)
{
cin>>w[i];
q.push((t1){0,w[i],i,true});
u[i]=i;
}
long long sum=0;
while(sum!=n&&h!=0)
{
t1 n1=q.top();
q.pop();
long long i=n1.i;
ans[i]++;
cnt[i]++;
h--;
sum+=(ans[i]==1);
q.push((t1){cnt[i],w[i],i,false});
}
if(h>0)
{
for(long long i=1;i<=n;i++)
{
ans[i]+=(h/n);
}
h%=n;
sort(u+1,u+n+1,cmp);
for(long long i=1;i<=h;i++)
{
ans[u[i]]++;
}
}
for(long long i=1;i<=n;i++)
{
cout<<ans[i]<<" ";
}
cout<<endl;
return 0;
}