CF:Permutations

Permutations

题面翻译

题目描述
“排列”是指一个长度为n的序列,且其中1到n的每个数刚好出现一次。例如,(1) (4,3,5,1,2) (3,2,1)都是排列,而(1,1) (4,3,1) (2,3,4)则不是。

假设某人拿了几个排列(长度不一定相同),把它们连在一起写成了一个数列,并将这个数列打乱顺序。你的任务是将这个数列重新组成原来的几个排列(如果可能的话)。

输入输出格式
输入格式:
第1行是一个整数n(1<=n<=105)。下一行是这个打乱后的n个整数,用一个空格隔开。这个数列中的数在1到105的范围内。

输出格式:
如果这个数列能被分成若干的排列,且数列中的每个数恰好属于一个排列,请在第1行输出排列的个数。第2行有n个数,对应着给定数列的n个数:如果第i个元素属于第1个排列,输出的这一行的第i个数就是1,如果它属于第2个排列,那么它对应的输出中的数就是2,等等。这些排列的顺序无关紧要。

如果有多种答案,输出其中任意一个。如果没有答案,在第1行输出-1.

说明
在第1个样例中数组被分成了三个排列:(2,1) (3,2,1,4,5) (1,2)。第1个排列由原数列的第2和4个数组成,第2个排列由第3、5、6、7、9个元素组成,第3个排列由第1和8个元素组成。显然,还有另外几种分组的方式。

题目描述

A permutation is a sequence of integers from 1 1 1to n n nof length n n ncontaining each number exactly once. For example, ( 1 ) (1) (1), ( 4 , 3 , 5 , 1 , 2 ) (4,3,5,1,2) (4,3,5,1,2), ( 3 , 2 , 1 ) (3,2,1) (3,2,1)are permutations, and ( 1 , 1 ) (1,1) (1,1), ( 4 , 3 , 1 ) (4,3,1) (4,3,1), ( 2 , 3 , 4 ) (2,3,4) (2,3,4)are not.

There are many tasks on permutations. Today you are going to solve one of them. Let’s imagine that somebody took several permutations (perhaps, with a different number of elements), wrote them down consecutively as one array and then shuffled the resulting array. The task is to restore the initial permutations if it is possible.

输入格式

The first line contains an integer n n n( 1 < = n < = 1 0 5 1<=n<=10^{5} 1<=n<=105). The next line contains the mixed array of n n nintegers, divided with a single space. The numbers in the array are from 1 1 1to 1 0 5 10^{5} 105.

输出格式

If this array can be split into several permutations so that every element of the array belongs to exactly one permutation, print in the first line the number of permutations. The second line should contain n n nnumbers, corresponding to the elements of the given array. If the i i i-th element belongs to the first permutation, the i i i-th number should be 1 1 1, if it belongs to the second one, then its number should be 2 2 2and so on. The order of the permutations’ numbering is free.

If several solutions are possible, print any one of them. If there’s no solution, print in the first line − 1 -1 1.

样例 #1

样例输入 #1

9
1 2 3 1 2 1 4 2 5

样例输出 #1

3
3 1 2 1 2 2 2 3 2

样例 #2

样例输入 #2

4
4 3 2 1

样例输出 #2

1
1 1 1 1

样例 #3

样例输入 #3

4
1 2 2 3

样例输出 #3

-1

提示

In the first sample test the array is split into three permutations: ( 2 , 1 ) (2,1) (2,1), ( 3 , 2 , 1 , 4 , 5 ) (3,2,1,4,5) (3,2,1,4,5), ( 1 , 2 ) (1,2) (1,2). The first permutation is formed by the second and the fourth elements of the array, the second one — by the third, the fifth, the sixth, the seventh and the ninth elements, the third one — by the first and the eigth elements. Clearly, there are other splitting variants possible.

思路:

这题首先要判断输入的数列能否被分成完整的若干的排列,如果不行,就直接输出-1结束,如果可以的话,先输出可以分成的个数,然后输出给定的各个数属于第几个排列里,只要输出其中一种。
首先解决第一个问题,先使用数组存入各个数,因为我打算使用sort排序来进行判断,所以会打乱顺序,所以得开一个新数组存相同的数据。sort排序后第一个数一定是1,且排序后的相邻的数不能相差1,然后数字越大的数出现次数不能比数字小的多,不然输出-1
如果可以分成的话,要输出各个数属于第几个个排列,可以使用map来记录出现次数,以原来的顺序遍历输出map中键的值,每输出一次键的值减1即可输出题目要求的顺序

代码

#include <bits/stdc++.h>
using namespace std;

int main() {
    int n;
    cin >> n;

    // 创建一个大小为 n 的整数向量 v 和 g
    vector<int> v(n), g(n);

    // 创建一个 map,用于记录每个元素在原序列中的出现次数
    map<int, int> mp;

    // 读取输入的整数序列,并同时更新 g 和 mp
    for (int i = 0; i < n; i++) {
        cin >> v[i];
        g[i] = v[i];
        mp[g[i]]++;
    }

    // 对 v 进行排序,用于后续判断是否可以分成连续子序列
    sort(v.begin(), v.end());

    // 如果排序后的序列的最小值不为 1,则无法分成连续子序列
    if (v[0] != 1) {
        cout << "-1\n";
        return 0;
    }

    int a = 0, b = mp[1];
    for (int i = 0; i < n; i++) {
        // 如果当前元素与前一个元素之差大于 1,则无法分成连续子序列
        if (i > 0 && v[i] - v[i - 1] > 1) {
            cout << "-1\n";
            return 0;
        }

        // 更新 a 和 b,用于判断当前子序列中相同元素的个数是否超过其在原序列中的出现次数
        if (i == 0) {
            a = 1;
        } else if (v[i] == v[i - 1]) {
            a++;
        } else {
            if (a > b) {
                cout << "-1\n";
                return 0;
            }
            b = a;
            a = 1;
        }
    }

    // 输出最大出现次数,并按照原序列的顺序输出各个元素的出现次数
    cout << mp[v[0]] << '\n';
    for (int i = 0; i < n; i++) {
        if (i == 0) {
            cout << mp[g[i]];
        } else {
            cout << ' ' << mp[g[i]];
        }
        mp[g[i]]--;
    }
    
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
### 回答1: permutations是Python中的一个函数,用于生成一个可迭代对象,其中包含给定序列中所有可能的排列组合。它的语法如下: permutations(iterable, r=None) 其中,iterable是要进行排列组合的序列,r是要生成的排列组合的长度,默认为None,表示生成所有可能的排列组合。 例如,对于序列[1,2,3],可以使用permutations函数生成所有可能的排列组合: from itertools import permutations lst = [1, 2, 3] for p in permutations(lst): print(p) 输出结果为: (1, 2, 3) (1, 3, 2) (2, 1, 3) (2, 3, 1) (3, 1, 2) (3, 2, 1) 可以看到,permutations函数生成了给定序列中所有可能的排列组合。 ### 回答2: 在Python中,permutations是一个内置函数,它被用于生成一系列的排列,并且可以接受一个可迭代序列作为输入参数。它的基本语法如下: permutations(iterable[, r]) 其中,iterable指定了要被生成排列的对象,它可以是列表、元组、字符串等等;r指定了每个排列的元素个数,默认为None,表示排列元素的个数和输入参数的长度相同。例如: from itertools import permutations # 生成列表的排列 lst = [1, 2, 3] perms = permutations(lst) print(list(perms)) # 输出:[(1, 2, 3), (1, 3, 2), (2, 1, 3), (2, 3, 1), (3, 1, 2), (3, 2, 1)] # 生成字符串的排列 s = "abc" perms = permutations(s) print(list(perms)) # 输出:[('a', 'b', 'c'), ('a', 'c', 'b'), ('b', 'a', 'c'), ('b', 'c', 'a'), ('c', 'a', 'b'), ('c', 'b', 'a')] 根据上面的例子,我们可以看到,permutations函数会生成可迭代对象,我们需要使用list函数将其转换为列表进行输出。需要注意的是,permutations函数返回的是元组类型,如果需要转换为其他类型,需要使用对应的转换函数或语句。 另外,当指定r参数时,permutations函数会生成长度为r的排列,例如: lst = [1, 2, 3] perms = permutations(lst, 2) print(list(perms)) # 输出:[(1, 2), (1, 3), (2, 1), (2, 3), (3, 1), (3, 2)] 例如上面的代码会生成lst中任意两个元素的排列。需要注意的是,当指定r参数时,permutations函数会把重复的元素当做不同的元素处理,因此需要注意去重的问题。如果需要去重,可以使用set函数将其转换为集合类型,或者使用ordered_set库进行去重操作。 总之,permutations是一个非常有用的工具,可以用于生成排列,进行组合等等高级操作,同时由于其是内置的Python函数,使用也非常便捷。 ### 回答3: Python中的permutations是一个用于生成给定列表中的所有可能排列的函数。这个函数可以用于得到一个可遍历对象(iterable),其包含了原列表中所有元素的所有可能排列。 permutations函数的语法如下:itertools.permutations(iterable, r=None)。其中iterable是指要进行排列的元素,r表示每个排列的固定长度,如果不指定,则默认为iterable的长度。 接下来我们将介绍一些关于permutations函数的常见用法: ### 生成所有排列 ``` from itertools import permutations a = [1,2,3] p = permutations(a) for i in p: print(i) ``` 这段代码将输出a列表中元素的所有排列方式,即: ``` (1, 2, 3) (1, 3, 2) (2, 1, 3) (2, 3, 1) (3, 1, 2) (3, 2, 1) ``` ### 指定每个排列的长度 ``` from itertools import permutations a = [1,2,3] p = permutations(a, 2) for i in p: print(i) ``` 这段代码将输出长度为2的所有排列方式,即: ``` (1, 2) (1, 3) (2, 1) (2, 3) (3, 1) (3, 2) ``` ### 对字符串进行排列 ``` from itertools import permutations a = "abc" p = permutations(a) for i in p: print(i) ``` 这段代码将输出字符串“abc”的所有排列方式,即: ``` ('a', 'b', 'c') ('a', 'c', 'b') ('b', 'a', 'c') ('b', 'c', 'a') ('c', 'a', 'b') ('c', 'b', 'a') ``` 通过permutations函数的使用,我们可以快速地生成所有可能的排列,可以应用于数学、密码学、电子商务等领域中的问题。需要注意的是,由于permutations函数的计算量较大,同时生成的排列次序是随机的,因此在实际应用时需要考虑时间复杂度以及随机性的影响。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值