C. Building Permutation

本文介绍了一个算法问题,即如何通过最少的加1或减1操作将一个整数序列转化为一个包含1到n的唯一整数的排列。文章提供了一种解决方案,包括对输入序列进行排序并计算每个元素与其目标位置之间的距离之和。

time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output

Permutation p is an ordered set of integers p1,  p2,  ...,  pn, consisting of n distinct positive integers, each of them doesn't exceed n. We'll denote the i-th element of permutation p as pi. We'll call number n the size or the length of permutationp1,  p2,  ...,  pn.

You have a sequence of integers a1, a2, ..., an. In one move, you are allowed to decrease or increase any number by one. Count the minimum number of moves, needed to build a permutation from this sequence.

Input

The first line contains integer n (1 ≤ n ≤ 3·105) — the size of the sought permutation. The second line contains n integersa1, a2, ..., an ( - 109 ≤ ai ≤ 109).

Output

Print a single number — the minimum number of moves.

Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the%I64d specifier.

Sample test(s)
input
2
3 0
output
2
input
3
-1 -1 2
output
6
Note

In the first sample you should decrease the first number by one and then increase the second number by one. The resulting permutation is (2, 1).

In the second sample you need 6 moves to build permutation (1, 3, 2).


解题说明:此题的意思就是如何通过最小的加1减1操作把原数列改造成只含1-n每个数字只含一次的数列。既然是最小的步数,那么我们应该把原数列中的每个数字尽量往其最接近的1-n中的数字靠。为此需要进行排序,然后通过对差的绝对值求和即可。


#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;

double a[300001];

int main()
{
	int n,i,j;
	double temp;
	double sum;
	sum=0;
	scanf("%d",&n);
	for(i=0;i<n;i++)
	{
		scanf("%lf", &a[i]);
	}
	sort(a,a+n);
	for(i=0;i<n;i++)
	{
		sum+=abs(i+1-a[i]);
	}
	printf("%.0lf\n",sum);
	return 0;
}


### 如何在 `np.random.permutation` 中设置随机数种子 为了确保每次运行程序时生成的结果一致,可以通过设置随机数种子来实现这一目标。以下是关于如何在使用 `np.random.permutation` 时设置随机数种子的具体方法。 #### 设置随机数种子的方法 在 NumPy 的 `random` 模块中,可以调用 `np.random.seed(seed_value)` 来设定随机数生成器的种子[^2]。一旦设置了种子值,在后续执行任何依赖于随机性的操作(如 `np.random.permutation` 或其他随机函数)时,都会基于相同的初始状态生成可重复的结果。 #### 示例代码 下面是一个完整的示例,展示如何通过设置种子值使 `np.random.permutation` 返回相同的结果: ```python import numpy as np # 设置随机数种子 np.random.seed(42) # 使用 np.random.permutation 对列表进行随机排序 result = np.random.permutation([1, 2, 3, 4, 5]) print(result) # 输出: [3 2 5 1 4] ``` 如果再次运行此代码片段而不更改种子值,则会得到完全一样的结果 `[3 2 5 1 4]`。这是因为随机数生成器的状态被固定下来了。 需要注意的是,当不显式指定种子时,默认情况下 NumPy 随机数生成器会在内部选取一个不可预测的时间戳作为默认种子值,因此每次运行可能会获得不同的排列顺序。 另外值得注意的一点是,虽然这里讨论的重点在于 `np.random.permutation` 方法的应用场景及其与种子的关系,但实际上整个 NumPy 库中的所有涉及随机化的功能都遵循同样的原则——即只要提前设定了全局范围内的种子(`np.random.seed`)之后再调用任意数量次此类函数均能重现之前产生的数据模式[^3]。 #### 更多扩展应用实例 对于更复杂的案例来说,比如希望打乱一个多维数组或者仅需部分元素被打散重排而不是整体改变位置关系的情形下,也可以利用类似的逻辑完成任务: ```python import numpy as np # 设定固定的随机数种子以便验证一致性 np.random.seed(42) multi_dim_array = np.arange(16).reshape((4, 4)) shuffled_rows = multi_dim_array[np.random.permutation(multi_dim_array.shape[0])] print(shuffled_rows) ``` 在这个例子当中,我们先创建了一个四行四列大小填充连续整数值构成二维矩阵;接着借助 `np.random.permutation()` 获取到重新安排后的索引序列作用于原始对象之上从而实现了按照行维度独立洗牌的效果而保持每行列内相对布局不变特性[^4]。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值