递推置换,交换次数最少得到升序序列

UVA11077

题意: 

给定一个1~n的排序,可以通过一系列的交换变成1,2,…,n, 给定n和k,统计有多少个排列至少需要交换k次才能变成有序的序列。

题解: 

每个长度为n循环需要交换n-1次才能将交换到对应的位置,例如1->2,2->4,4->1,(1,2,4)位置上对应值为(2,4,1) 相当于一个长度为3的环逆时针旋转了1格,要变换回来,需要跟原位置交换,因为成环,所以共n-1次     那么对于序列P,有x个循环节,长度为n,就需要交换n-x次     对于f[i][j],表示交换j次能变为1~i的序列的种数     我们找到递推式:f[i][j]=f[i-1][j]+f[i-1][j-1]*(i-1),边界是f[1][0]=1,其余为0     解释:新增的i,如果与自己构成循环,那么循环数和长度都加一,交换数不变,所以是f[i-1][j]         新增的i,如果参加到其他环中,每个数后一种,共i-1种,循环数不变,长度加一,所以是f[i-1][j-1]*(i-1)     例如1->2,2->3,3->1,{2,3,1};将4添加到1后就是1->4,4->2,2->3,3->1,序列为{4,3,1,2};其他同上

 1 #include<bits/stdc++.h>
 2 #define mp make_pair
 3 #define pb push_back
 4 #define first fi
 5 #define second se
 6 #define pw(x) (1ll << (x))
 7 #define sz(x) ((int)(x).size())
 8 #define all(x) (x).begin(),(x).end()
 9 #define rep(i,l,r) for(int i=(l);i<(r);i++)
10 #define per(i,r,l) for(int i=(r);i>=(l);i--)
11 #define FOR(i,l,r) for(int i=(l);i<=(r);i++)
12 #define eps 1e-9
13 #define PIE acos(-1)
14 #define cl(a,b) memset(a,b,sizeof(a))
15 #define fastio ios::sync_with_stdio(false);cin.tie(0);
16 #define lson l , mid , ls
17 #define rson mid + 1 , r , rs
18 #define ls (rt<<1)
19 #define rs (ls|1)
20 #define INF 0x3f3f3f3f
21 #define LINF 0x3f3f3f3f3f3f3f3f
22 #define freopen freopen("in.txt","r",stdin);
23 #define cfin ifstream cin("in.txt");
24 #define lowbit(x) (x&(-x))
25 #define sqr(a) a*a
26 #define ll long long
27 #define ull unsigned long long
28 #define vi vector<int>
29 #define pii pair<int, int>
30 #define dd(x) cout << #x << " = " << (x) << ", "
31 #define de(x) cout << #x << " = " << (x) << "
"
32 #define endl "
"
33 using namespace std;
34 //**********************************
35 ull dp[25][25];//dp[i][j]表示前i个数至少用k次交换的排列数 
36 int n,k;
37 //**********************************
38 void Init()
39 {
40     FOR(i,1,21){
41         dp[i][0]=1;
42         rep(j,1,i){
43             dp[i][j]=dp[i-1][j-1]*(i-1)+dp[i-1][j];;
44         }
45     }
46 }
47 //**********************************
48 int main()
49 
50 {
51     Init();
52     while(cin>>n>>k,n+k){
53         cout<<dp[n][k]<<endl;
54     }
55     return 0;
56 }
View Code
原文地址:https://www.cnblogs.com/klaycf/p/9682046.html