C. Pinkie Pie Eats Patty-cakes
题意: 有 n 个已知种类的蛋糕,求如何吃掉这 n 个蛋糕使得,相同种类的蛋糕之间的蛋糕距离最大,求最大吃法中的相同蛋糕的最小距离(两个相同蛋糕之间的距离为其之间的蛋糕数)。
思路: 所以,如何构造才能使得相同蛋糕之间的距离最大呢,我们把种类最多的蛋糕数设为 k 个 ,显然分开放后会产生k-1个间隔,所以我们把剩下的蛋糕分别填充这k-1个间隙,然后找个最小的距离即可。
注意 :k 可能会出现多个。
Code1:
隔板思想。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+7;
int vis[N];
int main()
{
int T;cin>>T;
while(T--){
int n,t,k=0;
cin>>n;
for(int i=1;i<=n;i++) vis[i]=0;
for(int i=0;i<n;i++){
scanf("%d",&t);
k = max(k,++vis[t]);
}
if(k==1) {
printf("%d\n",n-1);continue;
}
int num=0;
for(int i=1;i<=n;i++) if(vis[i]==k) num++;
printf("%d\n",(n-num*k)/(k-1)+num-1);
}
return 0;
}
Code2:
二分答案(间距),check 时判断是否把所有蛋糕安置在n个位置。其构造结果是和 code1 一致的。
#include<bits/stdc++.h>
using namespace std;
const int N = 1e6+7;
int vis[N],n;
vector<int> ve;
int num;
bool check(int k)
{
int s = 1;
for(int i=0;i<num;i++){
int t = ve[i];
for(int j=s;j<=n&&t;j += k+1) t--;
if(t) return 0;
s++;
}
return 1;
}
int main()
{
int T;cin>>T;
while(T--){
int t;
cin>>n;
ve.clear();
for(int i=0;i<n;i++){
scanf("%d",&t);
vis[t]++;
}
for(int i=1;i<=n;i++) if(vis[i]) ve.push_back(vis[i]),vis[i]=0;
sort(ve.begin(),ve.end(),greater<int>());
num = ve.size();
if(num==1){
printf("0\n");continue;
}
int l=0,r=n;
while(l<=r){
int mid = l+r>>1;
if(check(mid)) l = mid + 1;
else r = mid - 1;
}
printf("%d\n",l-1);
}
return 0;
}