题意:
给定一个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};其他同上
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
1 #include2 #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-913 #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 , ls17 #define rson mid + 1 , r , rs18 #define ls (rt<<1)19 #define rs (ls|1)20 #define INF 0x3f3f3f3f21 #define LINF 0x3f3f3f3f3f3f3f3f22 #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*a26 #define ll long long27 #define ull unsigned long long28 #define vi vector 29 #define pii pair 30 #define dd(x) cout << #x << " = " << (x) << ", "31 #define de(x) cout << #x << " = " << (x) << "\n"32 #define endl "\n"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< <