JZOJ 5253. 排列与交换
2017-09-29 21:34
267 查看
Description
一个数组A = [1, 2, 3, …, n]。对A进行好恰好k次相邻交换,能得到多少个不同的序列 (S1)?
对A进行最多k次交换,你能得到多少个不同的序列 (S2)?
一次相邻交换是指交换数组A中两个相邻位置的元素,即:交换A[i]和A[i+1]或者A[i]和A[i-1]。
一次交换是指交换数组A中的任意两个位置不同的元素,即:交换A[i]和A[j],1 <= i, j <= N, i != j。
给出数组A的长度N,以及次数K,求S1和S2。由于结果很大,输出Mod 1000000007的结果。
例如:原始数组: [1, 2, 3]
经过两次相邻交换:
我们得到 [1, 2, 3], [2, 3, 1], [3, 1, 2] ==> S1 = 3
经过最多两次交换:
1) 0次交换后: [1, 2, 3]
2) 1次交换后: [2, 1, 3], [3, 2, 1], [1, 3, 2].
3) 两次交换后: [1, 2, 3], [2, 3, 1], [3, 1, 2] ==> S2 = 6
Input
数组A的长度N,以及次数K。Output
S1和S2。由于结果很大,输出Mod 1000000007的结果。Sample Input
5 10Sample Output
60 120Data Constraint
对于50%数据N,K<=500对于100%数据1<=N, K<=3000
Solution
问题分为两个子问题:恰好 k 次相邻交换的排列数、最多 k 次交换排列数。对于第一个子问题,设 F[i][j] 表示做到第 i 个数,交换次数为 j 能得到的排列数。
首先继承上一个 F[i][j]=f[i−1][j]
不过当 i 交换到第 1 个位置之后,再换就会算重,所以:F[i][i+j]−=F[i−1][j]
最后: F[i][j]+=F[i][j−1]
(这里是不断向前交换)。
这样最后的答案就是 F[n][i] (k−i是偶数) ,即剩下 k−i 步可以不断的交换相邻两个来达到。
对于第二个子问题,就相对比较简单了。
同样设 F[i][j] 表示做到第 i 个数,交换次数为 j 能得到的排列数。
那么则有:F[i][j]=F[i−1][j]+F[i−1][j−1]∗(i−1)
因为对于第 i 个数无非就是不交换或者与前 i−1 个数交换。
显然答案即为:∑i=0kF[n][i]
这样两个 DP 的时间复杂度都是 O(NK) ,则总复杂度为 O(NK) 可过本题。
Code
#include<cstdio> #include<cstring> using namespace std; const int mo=1e9+7; int n,k,roll,ans; int f[2][3002]; int main() { scanf("%d%d",&n,&k); for(int i=f[0][0]=1;i<=n;i++) { roll^=1; memset(f[roll],0,sizeof(f[roll])); for(int j=0;j<=k;j++) { f[roll][j]=((long long)f[roll][j]+f[roll^1][j]+f[roll][j-1])%mo; if(i+j<=k) f[roll][i+j]=(f[roll][i+j]+mo-f[roll^1][j])%mo; } } for(int i=0;i<=k;i++) if(!(k-i&1)) ans=(ans+f[roll][i])%mo; printf("%d ",ans); memset(f[0],ans=roll=0,sizeof(f[0])); for(int i=1;i<=n;i++) { roll^=1; memset(f[roll],0,sizeof(f[roll])); f[roll][0]=1; for(int j=1;j<=k;j++) f[roll][j]=(f[roll^1][j]+(long long)f[roll^1][j-1]*(i-1))%mo; } for(int i=0;i<=k;i++) ans=(ans+f[roll][i])%mo; printf("%d",ans); return 0; }
相关文章推荐
- 【CROC 2016 - Elimination RoundB】【贪心】Mischievous Mess Makers 全排列1到n交换k次最多逆序数
- “全排列”问题系列(一)[LeetCode] - 用交换元素法生成全排列及其应用,例题: Permutations I 和 II, N-Queens I 和 II,数独问题
- 打印数组a{1,2,...,n}的全排列(交换)
- 给定一个5*5的矩阵(数学上,一个r×c的矩阵是一个由r行c列元素排列成的矩形阵列),将第n行和第m行交换,输出交换后的结果。
- 【codeforces 691 D】【并查集 或者 dfs】aps in Permutation【给一个1到N的排列,M个操作,每次可以交换X Y位置上的数字,求可以得到的最大字典序的数列】
- [置顶] 【JZOJ5429】【NOIP2017提高A组集训10.27】排列
- Jzoj3163 排列
- JZOJ5235. 【NOIP2017模拟8.7A组】好的排列
- 全排列(交换,递归,有详细解释)
- 全排列-相邻交换法
- Day 5 jzoj 4310. 【NOIP2015模拟11.4】最优交换
- jzoj3775 [NOIP2014模拟8.15]因子的排列
- JZOJ 5235. 【NOIP2017模拟8.7A组】好的排列
- 两元素交换的排列组合问题
- JZOJ 5598 全排列
- jzoj4310 最优交换
- 字符串全排列【方法2:利用交换的思想】
- 两两交换(相邻)得到一个有序排列
- 【算法】求全排列 回溯 交换 DFS JAVA
- JZOJ 3775. 【NOIP2014模拟8.15】因子的排列