UVA11077 循环群计数

本文详细介绍了如何解决UVA11077问题,即计算n个数的排列中至少需要进行k次两两交换才能变为特定顺序的排列的数量。通过引入循环群的概念,提出了一种高效的算法来解决这一问题,并提供了相应的代码实现。重点阐述了算法的原理、关键步骤以及如何通过数学公式和代码来验证算法的有效性。
 1 /*UVA11077
 2 循环群计数
 3 n个数的排列数P(n)=n!
 4 一个n的排列可以通过两两交换变成一个(123..n)的顺序排列
 5 判断方法我们熟知,把这个排列写生不相交循环,最少操作数d=n-循环群个数x
 6 现在问题求的是多少个n的排列至少通过k次两两交换。
 7 现在逐步分析:
 8 设f(n,k)为n的排列,通过k次最少交换
 9 f(n,k)=f(n-1,k)+f(n-1,k-1)*(n-1)//这点白书上有错误
10 解释:f(n-1,k-1),循环群个数n-k个,变成f(n,k),不需要新增循环群,将数字n插入前n-1个位置都可
11 同理,f(n-1,k),循环群个数n-k-1个,变成f(n,k),要新增一个循环群,故n单独成循环群,放置在最后
12 边界f(i,0)=1;其他为0
13 注意测试大数字
14 */
15 #include<iostream>
16 #include<stdio.h>
17 #include<string.h>
18 #include<algorithm>
19 #include<stdlib.h>
20 #include<math.h>
21 #include<queue>
22 #include<vector>
23 #include<map>
24 #define ULL unsigned long long
25 using namespace std;
26 
27 int n,k;
28 ULL F[25][25];
29 void init(){
30     memset(F,0,sizeof(F));
31     for(int i=1;i<=21;i++)F[i][0]=1;
32     for(int i=2;i<=21;i++){
33         for(int j=1;j<i;j++)
34             F[i][j]=F[i-1][j-1]*(i-1)+F[i-1][j];
35     }
36     return ;
37 }
38 int main(){
39     init();
40     while(cin>>n>>k ){
41         if (n==0 && k==0) break;
42         cout<<F[n][k]<<endl;
43 
44     }
45     return 0;
46 }

 

转载于:https://www.cnblogs.com/little-w/p/3570260.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值