Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/cplusplus/140.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C++ 求满足给定条件的置换_C++_Algorithm_Count_Permutation - Fatal编程技术网

C++ 求满足给定条件的置换

C++ 求满足给定条件的置换,c++,algorithm,count,permutation,C++,Algorithm,Count,Permutation,我想找出nnnumber的所有排列的个数。个数将从1到n。给定的条件是每个位置的个数都可以达到Si,其中每个位置的个数都是Si 1<=n<=10^6 1<=si<=n 那么它的所有五个元素都是 1,2,3,4,5 每个位置的给定Si如下所示: 2,3,4,5,5 这表明: 第一个位置可以有1到2,即1,2,但不能是3到5之间的数字。 同样地, 第二个位置只能有数字1到3。 第三个位置只能有1到4个数字。 第四位只能有数字1到5。 第5位只能有数字1到5。 它的一些排

我想找出nnnumber的所有排列的个数。个数将从1到n。给定的条件是每个位置的个数都可以达到Si,其中每个位置的个数都是Si

1<=n<=10^6
1<=si<=n
那么它的所有五个元素都是

1,2,3,4,5
每个位置的给定Si如下所示:

2,3,4,5,5
这表明: 第一个位置可以有1到2,即1,2,但不能是3到5之间的数字。 同样地, 第二个位置只能有数字1到3。 第三个位置只能有1到4个数字。 第四位只能有数字1到5。 第5位只能有数字1到5。 它的一些排列是:

1,2,3,4,5
2,3,1,4,5
2,3,4,1,5 etc.
但这些不能是:

3,1,4,2,5  As 3 is present at 1st position.
1,2,5,3,4  As 5 is present at 3rd position.

我不知道在给定的条件下计算所有可能的排列数

您可以尝试回溯,这是一种有点核心的方法,但会奏效。 尝试:
或者google backtracking tutorial C++

为每个si计算数组中的元素数,这样[i]好的,如果我们保证数字si不是按降序给出的,那么看起来可以计算On中的排列数

直截了当算法的思想如下:

在步骤i,将结果乘以si[i]的当前值; 我们为职位i选择了一些号码。只要我们需要排列,这个数字就不能重复,所以将所有剩余的si[k]从i+1减到最后,例如n减1; 将i增加1,返回1。 举例说明si:2 3 4:

结果=1; 当前si为2 3 4,结果*=si[0]=1*2==2,将3、3和4减少1; 当前si为..2 2 3,结果*=si[1]=2*2==4,最后2和3减少1; 当前si为…12,结果*=si[2]=4*1==4,将最后一个数字减少1; 当前si为。。。。。1,结果*=si[3]=4*1==4,完成。 由于步骤减少,这种简单的方法需要在^2上运行。为了优化它,我们可以很容易地观察到,在结果*=si[i]的时刻,我们的si[i]已经精确地减少了i倍,当然假设我们从0开始

因此,在路上:


要完成Yuriy Ivaskevych的回答,如果您不知道sis的顺序是否在增加,您可以对sis进行排序,它也会起作用。
如果排列不可能,则结果将为空或负,例如:1

这是某种编码竞赛吗?还是判断问题?它不属于任何正在运行的编码竞赛。但它需要我的编码实现。@coderredoc已提到n和Si的给定限制。您只需要排列的数量还是排列本身也是吗?对于您的示例,可以进行多少置换?@Yuriy只有置换的数量。n最多为1e6,这将得到TLE,即使在^2上也会得到TLE。@Alex Banu,我对回溯知之甚少,请解释如何实现回溯以解决此问题。
3,1,4,2,5  As 3 is present at 1st position.
1,2,5,3,4  As 5 is present at 3rd position.
unsigned int result = 1;
for (unsigned int i = 0; i < n; ++i)
{
    result *= (si[i] - i);
}