uva 11077 Find the Permutations 置换+递推

6 篇文章 0 订阅


Sorting is one of the most usedoperations in real life, where Computer Science comes into act. It iswell-known that the lower bound of swap based sorting is nlog(n).It means that the best possible sorting algorithm will take at least W(nlog(n))swaps to sort a set of nintegers. However, to sort a particular array of n integers, you can alwaysfind a swapping sequence of at most (n-1) swaps, once you know theposition of each element in the sorted sequence. For example – consider fourelements <1 2 3 4>. There are 24 possible permutations and for allelements you know the position in sorted sequence.

 

If the permutation is <2 1 43>, it will take minimum 2 swaps to make it sorted. If the sequence is<2 3 4 1>, at least 3 swaps are required. The sequence <4 2 31> requires only 1 and the sequence <1 2 3 4> requires none. In thisway, we can find the permutations of Ndistinct integers which will take at least K swaps to be sorted.

Input

Each input consists of two positiveintegers N (1≤N≤21) and K (0≤K<N) in a single line. Inputis terminated by two zeros. There can be at most 250 test cases.

Output

For each of the input, print in aline the number of permutations which will take at least K swaps.

SampleInput                             Output for Sample Input

3 1

3 0

3 2

0 0

 

3

1

2

 


Problemsetter: Md. Kamruzzaman

Special Thanks: Abdullah-al-Mahmud


题意:问你一个长度n的排列,需要k次才能变换成有序排列的个数是多少个

题解:在一个长度为m的置换里,变成有序需要m-1次,然后需要k次,可以用递推来做

dp[i][j]表示1-i变成有序,需要j次的排列个数

dp[i][j]=dp[i-1][j]+d[i-1][j-1]*(i-1),这是说明i要么自己成为一个循环,前面i-1个数字用了j次交换,要么就是i加入前面的置换里,和前面i-1个数中任意一个换一下位置,所以乘i-1,这样就多了一次交换

这题会爆long long,用unsigned long long

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef unsigned long long ull;
ull dp[25][25];
int main()
{
    int n, k;
    while(~scanf("%d%d", &n, &k), k+n)
    {
        memset(dp, 0, sizeof(dp));
        dp[1][0] = 1;
        for(int i = 2; i <= n; i++)
            for(int j = 0; j < i; j++)
            {
                dp[i][j] = dp[i-1][j];
                if(j) dp[i][j] += dp[i-1][j-1]*(i-1);
            }
        printf("%llu\n", dp[n][k]);
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值