我正在编写一个使用替换密码加密明文的程序。我试图计算总数,因为缺乏一个更好的术语“密码”排列。我的意思是,我想计算所有可能无法替代明文本身的排列。含义00000000(NULL)不能替换为00000000(NULL)。我知道我可以通过以下方式生成n个块的所有可能的排列。
n(大小)= 3(1,2,3是被置换的唯一值)
问题是,只有231和312不能将纯文本替换为自身。我可以使用条件语句来确定排列是否有效但我更喜欢一种只计算有效排列的方法。我希望已经有一种简单的方法可以做到这一点,但我不知道该怎么说这个问题才能谷歌。因此,总结一下我的问题,我需要一种有效的方法来计算所有可能不会使明文未被取代的密码排列。
以下代码将为n个唯一值生成所有可能的排列。但它只会在n时起作用!可以使用普通的整数数据类型表示。
#include <stdlib.h>
#include <stdio.h>
int main()
{
int current_perm = 0;
int num_perms = 1;
int cypher_size = 0;
int buffer = 0;
int *cypher = NULL;
printf("Input the number of unique values in the cypher(The cypher's size) : ");
scanf("%i", &cypher_size);
if((cypher = malloc(sizeof(int)*(cypher_size+1))) == NULL)
{
perror("ERROR: Failed to allocate memory for the cypher ");
return 1;
}
int i = cypher_size;
int j = 0;
while(i > 0)
{
cypher[i-1] = i;
num_perms *= i;
i--;
}
for(j = 0; j < cypher_size; j++) {printf("%i ", cypher[j]);}
printf("\n");
for(current_perm = 1; current_perm < num_perms;)
{
for(i = 0; i < cypher_size-1; i++, current_perm++)
{
buffer = cypher[i+1];
cypher[i+1] = cypher[i];
cypher[i] = buffer;
for(j = 0; j < cypher_size; j++) {printf("%i ", cypher[j]);}
printf("\n");
}
}
}
答案 0 :(得分:2)
没有固定点的排列称为derangements。以下C代码使用维基百科链接中的交替和公式。
static int nder(int n) {
int m = 1;
int f = 1;
for (int k = n; k > 0; k--) {
f *= k;
m = f - m;
}
return m;
}
你可以将int换成bignums或double。在后一种情况下,你应该得到一个准确的几个ulp内的答案。如果答案不符合偶数,则ln(n!/ e)= ln(1)+ ln(2)+ ... + ln(n) - 1 = lgamma(n + 1.0) - 1.0
如果你有{ lgamma
中提供的{1}}是紊乱数量的自然对数的极佳近似值。