Description

统计 \(1...n\) 的排列,恰好进行 \(k\) 次相邻交换和至多进行 \(k\) 次交换生成的不同的序列个数.

Sol

DP.

好妙的题啊...

首先看第一个问题.

对于相邻元素的交换,我们建立状态 \(f[i][j]\) 表示前 \(i\) 个数进行 \(j\) 次交换的方案数.

我们分类来讨论 \(i\) 元素是否参与交换.

如果不参与交换 \(f[i][j]+=f[i-1][j]\)

如果参与交换,那么它最远能交换到的位置就是 \(i-j\) \(f[i][j]+=f[i-1][u],max\{ i-j,0 \}\leqslant u \leqslant j-1\)

其实合起来就是 \(f[i][j]=\sum_{u=max\{0,i-j\}} ^{j} f[i-1][u]\) ,前缀和搞一下就可以了.

然后第二个问题.

继续来分类讨论 \(i\) 元素是否参与交换.

如果不参与交换 \(f[i][j]+=f[i-1][j]\)

如果参与交换,那么它可以和前面任意一个元素交换 \(f[i][j]+=f[i-1][j-1]*(i-1)\)

非常简单啊...

至于最后的判重就更简单了,因为换两次可以换回来,那么就让 \(f[i][j]-f[i][j-2]\) 这才是 \(f[i][j]\) 真正的贡献.

PS:我好像卡常卡到第一了...

Code

#include<cstdio>
#include<iostream>
using namespace std; typedef long long LL;
const int N = 3005;
const LL p = 1000000007;
#define debug(a) cout<<#a<<"="<<a<<" " int n,k;
LL f[N][N]; int main(){
cin>>n>>k;
f[1][0]=1;
for(int i=0;i<=k;i++) f[2][i]=i+1;
for(int i=3;i<=n;i++) for(int j=0;j<=k;j++){
int l=j-min(j,i-1)-1;
f[i][j]=(f[i-1][j]-(l>=0?f[i-1][l]:0LL)+p)%p;
f[i][j]=(f[i][j]+f[i][j-1])%p;
}
//for(int i=1;i<=n;i++) for(int j=0;j<=k;j++) printf("%lld%c",f[i][j]," \n"[j==k]);
cout<<(f[n][k]-f[n][k-1]+p)%p<<" "; f[1][0]=1;
for(int i=0;i<=k;i++) f[2][i]=1;
for(int i=3;i<=n;i++) for(int j=0;j<=k;j++){
f[i][j]=f[i-1][j];
f[i][j]=(f[i][j]+f[i-1][j-1]*(i-1)%p)%p;
}
//for(int i=1;i<=n;i++) for(int j=0;j<=k;j++) printf("%lld%c",f[i][j]," \n"[j==k]);
LL ans=0;
for(int i=k;i>1;i--) ans=(ans+f[n][i]-f[n][i-2]+p)%p;
ans=(ans+f[n][0]+f[n][1])%p;
cout<<ans<<endl; return 0;
}

  

Code

51Nod 1250 排列与交换的更多相关文章

  1. 51nod 1250 排列与交换——dp

    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1250 仔细思考dp. 第一问,考虑已知 i-1 个数有多少种方案. ...

  2. 51Nod 1250 排列与交换 —— DP

    题目:http://www.51nod.com/onlineJudge/questionCode.html#!problemId=1250 看了半天... 把第一问想成逆序对的话似乎很容易想了,新加入 ...

  3. php实现字符串的排列(交换)(递归考虑所有情况)

    php实现字符串的排列(交换)(递归考虑所有情况) 一.总结 交换: 当有abc的时候,分别拿第一位和其它位交换,第一位固定,余下的位做递归,这样有考虑到所有情况,因为第一位只可能是所有的字母,那第一 ...

  4. 51nod 1574 排列转换(贪心+鸽巢原理)

    题意:有两个长度为n的排列p和s.要求通过交换使得p变成s.交换 pi 和 pj 的代价是|i-j|.要求使用最少的代价让p变成s. 考虑两个数字pi和pj,假如交换他们能使得pi到目标的距离减少,p ...

  5. 51nod 1574 排列转换(猜结论)

    分析 猜了一下结论,居然对了..........具体操作是:假设排列s是1,2,3,...,nk为排列p中最大的 没有放到正确位置的数,k的位置为posk的右边一定有一个数x<=pos(因为&l ...

  6. 51nod 1843 排列合并机(DP+组合)

    题解链接 不过求ggg不用O(n2)DPO(n^2)DPO(n2)DP,g[n]g[n]g[n]直接就是卡特兰数的第n−1n-1n−1项.即: g[n]=(2(n−1)n−1)−(2(n−1)n−2) ...

  7. 对象的比较与排序:IComparable和IComparer接口

    IComparable和ICompare 接口是.net framework 中比较对象的标准方式,这两个接口提供一个返回值类似(大于0 等于0 小于0)的比较方法,二者区别如下: . ICompar ...

  8. UVa 11077 (循环分解 递推) Find the Permutations

    把{1, 2, 3,,, n}叫做自然排列 本题便是求有多少个n元排列P要至少经过k次交换才能变为自然排列. 首先将排列P看做置换,然后将其分解循环,对于每个长度为i的循环至少要交换i-1次才能归位. ...

  9. CF(441D Valera and Swaps)置换群

    题意:1-n的一个排列, p2, ..., pn,f(p)的定义是此排列要交换最少的数对能够回到原排列1,2,3,4...n.给一个排列p.要将其变换成f值为m的排列,问至少要交换几个数对,并输出字典 ...

随机推荐

  1. win7开防火墙,允许ping通

  2. JavaWeb学习笔记——XML和SAX解析区别

  3. Java数据结构——队列

    //================================================= // File Name : Queue_demo //-------------------- ...

  4. 一个有趣的模拟光照的shader

    一个有趣的模拟光照的shader(类似法线贴图) http://www.cnblogs.com/flytrace/p/3395911.html -----  可否用于需UI中需要加灯的模型.

  5. nuget包管理器控制台下的powershell脚本介绍

    http://personball.com/powershell/2016/07/15/powershell-tips 定制自己的powershell,减少重复工作 安装一系列自己的常用nuget包 ...

  6. JSTL I18N 格式标签库

    <%@ page language="java" pageEncoding="gbk"%> <%@ taglib prefix="c ...

  7. MD5 (摘要加密)

    MD5 约定 同样的密码,同样的加密算法,每次加密的结果是不一样 密码方案 方案一:直接 MD5 pwd = pwd.md5String; 非常不安全 方案二 MD5 + 盐 pwd = [pwd s ...

  8. 【转】Flume日志收集

    from:http://www.cnblogs.com/oubo/archive/2012/05/25/2517751.html Flume日志收集   一.Flume介绍 Flume是一个分布式.可 ...

  9. matlab 聚类

    目前已知matlab的聚类方法有三种: 一.利用 clusterdata函数对样本数据进行一次聚类,其缺点为可供用户选择的面较窄,不能更改距离的计算方法: 二.层次聚类,该方法较为灵活,需要进行细节了 ...

  10. PHP从零开始-笔记-面向对象编程的概念

    面向对象变成的概念 需要一一种不同的方式来考虑如何构造应用程序.通过对象可以在对应用程序所处理的显示任务.过程和思想进行编码是,实施更贴切的建模.OOP方法并不是将应用程序考虑成一个将大量数据从一个函 ...