Codeforces 1393 C - Pinkie Pie Eats Patty-cakes(构造)

Pinkie Pie has bought a bag of patty-cakes with different fillings! But it appeared that not all patty-cakes differ from one another with filling. In other words, the bag contains some patty-cakes with the same filling.

Pinkie Pie eats the patty-cakes one-by-one. She likes having fun so she decided not to simply eat the patty-cakes but to try not to eat the patty-cakes with the same filling way too often. To achieve this she wants the minimum distance between the eaten with the same filling to be the largest possible. Herein Pinkie Pie called the distance between two patty-cakes the number of eaten patty-cakes strictly between them.

Pinkie Pie can eat the patty-cakes in any order. She is impatient about eating all the patty-cakes up so she asks you to help her to count the greatest minimum distance between the eaten patty-cakes with the same filling amongst all possible orders of eating!

Pinkie Pie is going to buy more bags of patty-cakes so she asks you to solve this problem for several bags!

Input
The first line contains a single integer 𝑇 (1≤𝑇≤100): the number of bags for which you need to solve the problem.

The first line of each bag description contains a single integer 𝑛 (2≤𝑛≤105): the number of patty-cakes in it. The second line of the bag description contains 𝑛 integers 𝑎1,𝑎2,…,𝑎𝑛 (1≤𝑎𝑖≤𝑛): the information of patty-cakes’ fillings: same fillings are defined as same integers, different fillings are defined as different integers. It is guaranteed that each bag contains at least two patty-cakes with the same filling.

It is guaranteed that the sum of 𝑛 over all bags does not exceed 105.

Output
For each bag print in separate line one single integer: the largest minimum distance between the eaten patty-cakes with the same filling amongst all possible orders of eating for that bag.

Example
inputCopy
4
7
1 7 1 6 4 4 6
8
1 1 4 6 4 6 4 7
3
3 3 3
6
2 5 2 3 1 4
outputCopy
3
2
0
4
Note
For the first bag Pinkie Pie can eat the patty-cakes in the following order (by fillings): 1, 6, 4, 7, 1, 6, 4 (in this way, the minimum distance is equal to 3).

For the second bag Pinkie Pie can eat the patty-cakes in the following order (by fillings): 1, 4, 6, 7, 4, 1, 6, 4 (in this way, the minimum distance is equal to 2).

题意:
一些数,有些数相同。求一个排列方式使得相同数的最小距离最大。

思路:
因为要使得最小距离最大,所以先直接考虑最小距离。
先考虑相同数最多的一部分,假设是x。我们只需要先填x,然后其他数全部填到x中间即可,这样肯定满足其他相同数距离不会小于x与x的最小距离。

因为只考虑最小距离,所以要尽量使得x间的数字个数均分。所以只需要将数顺序填入即可。

但是注意x出现y次,那就对应y-1个空格,最后一个x可以不需要考虑。要是出现多个出现次数相同的数,都要把最后一个数忽略。

最后假设一共有ans个数(将最大数目减一,有多个则都减一),最大出现次数为num。则答案为 a n s / ( n u m − 1 ) + 1 ans/(num-1)+1 ans/(num1)+1

再特判一下只有一种数的情况即可。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
const int mod = 1e9 + 7;

int a[maxn],vis[maxn],num[maxn];
map<int,int>mp;

int cmp(int x,int y) {
    return x > y;
}

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        mp.clear();
        int n;scanf("%d",&n);
        int cnt = 0;
        for(int i = 1;i <= n;i++) {
            scanf("%d",&a[i]);
            vis[i] = 0;
            num[i] = 0;
            if(!mp[a[i]]) mp[a[i]] = ++cnt;
            a[i] = mp[a[i]];
        }
        for(int i = 1;i <= n;i++) vis[a[i]]++;
        sort(vis + 1,vis + 1 + cnt,cmp);
        int len = vis[1];
        if(cnt == 1) {
            printf("0\n");
            continue;
        }
        
        int flag = 0;
        int ans = 0;
        for(int i = 1;i <= n;i++) {
            if(vis[i] == len) vis[i]--;
        }
        for(int i = 1;i <= n;i++) {
            ans += vis[i];
        }
        len--;
        
        printf("%d\n",ans / len - 1);
        
    }
    return 0;
}


不知道为什么要sb去写模拟,然后写错下标了。

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <map>

using namespace std;
typedef long long ll;
const int maxn = 2e5 + 7;
const int mod = 1e9 + 7;

int a[maxn],vis[maxn],num[maxn];
map<int,int>mp;

int cmp(int x,int y) {
    return x > y;
}

int main() {
    int T;scanf("%d",&T);
    while(T--) {
        mp.clear();
        int n;scanf("%d",&n);
        int cnt = 0;
        for(int i = 1;i <= n;i++) {
            scanf("%d",&a[i]);
            vis[i] = 0;
            num[i] = 0;
            if(!mp[a[i]]) mp[a[i]] = ++cnt;
            a[i] = mp[a[i]];
        }
        for(int i = 1;i <= n;i++) vis[a[i]]++;
        sort(vis + 1,vis + 1 + cnt,cmp);
        int len = vis[1];
        if(cnt == 1) {
            printf("0\n");
            continue;
        }
        
        int flag = 0;
        for(int i = 1;i <= n;i++) {
            if(vis[i] == len) vis[i]--;
        }
        len--;
        
        int now = 1;
        for(int i = 1;i <= cnt;i++) {
            int tmp = vis[i];
            while(tmp) {
                tmp--;
                num[now]++;
                now = now + 1;
                if(now == len + 1) now = 1;
            }
        }
        printf("%d\n",num[len] - 1);

    }
    return 0;
}
//7 9 3 8 10 2 4 8 3 9
//2 3 3 4 7 8 8 9 9 10

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值