zoukankan      html  css  js  c++  java
  • UVA11077 Find the Permutations

    题意

    PDF
    给出1~n的一个排列,可以通过一系列的交换变成{1,2,…,n}。比如{2,1,4,3}需要两次交换。给定n和k,统计有多少个排列至少需要k次交换才能变成{1,2,…,n}。

    分析

    将给出的排列P视为一个置换,并将其分解为循环,各循环间相互独立。

    单元素循环是不需要交换的,两个元素的循环需要交换1次,3个元素的循环需要交换2次,…,c个元素的循环需要交换c-1次。

    于是我们就可以采用递推的方式进行求解了。设f(i,j)表示至少需要交换j次才能变成{1,2,…,i}的排列个数。则f(i,j) = f(i - 1,j) + f(i – 1,j - 1) * (i - 1)。因为要么元素i自己形成一个循环,要么加入前面任意一个循环的任意一个位置。边界为f(1,0) = 1,f(1,j) = 0(j >= 1)。

    时间复杂度(O(n^2))

    代码

    #include<bits/stdc++.h>
    #define rg register
    #define il inline
    #define co const
    template<class T>il T read(){
        rg T data=0,w=1;rg char ch=getchar();
        while(!isdigit(ch)) {if(ch=='-') w=-1;ch=getchar();}
        while(isdigit(ch)) data=data*10+ch-'0',ch=getchar();
        return data*w;
    }
    template<class T>il T read(rg T&x) {return x=read<T>();}
    typedef unsigned long long ull;
    
    co int N=22;
    ull f[N][N];
    int main(){
    //	freopen(".in","r",stdin),freopen(".out","w",stdout);
    	f[1][0]=1;
    	for(int i=2;i<=21;++i)
    		for(int j=0;j<i;++j){
    			f[i][j]=f[i-1][j];
    			if(j>0) f[i][j]+=f[i-1][j-1]*(i-1);
    		}
    	for(int n,k;read(n)|read(k);) printf("%llu
    ",f[n][k]);
    	return 0;
    }
    
  • 相关阅读:
    NetCore物联网平台 4
    NetCore物联网平台 3
    NetCore物联网平台 2
    NetCore物联网平台 1
    阿里云IoT 8:待更新
    阿里云IoT 7:待更新
    阿里云IoT 6:待更新
    阿里云IoT 5:待更新
    阿里云IoT 4:数据解析
    svg 实现半环形进度条
  • 原文地址:https://www.cnblogs.com/autoint/p/10641910.html
Copyright © 2011-2022 走看看