博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
51nod 1250 排列与交换——dp
阅读量:6251 次
发布时间:2019-06-22

本文共 1203 字,大约阅读时间需要 4 分钟。

题目:

仔细思考dp。

第一问,考虑已知 i-1 个数有多少种方案。再放入一个数,它是最大的且在最后面,所以它的位置不同的话,就是不同的方案。它在特定的位置,其余部分的值就是 i-1 的值。

  所以再用前缀和优化成 n^2 即可。k可减任意个2。

第二问,还是像上面一样考虑。但新来的数只会和前面的数交换一次。任何一种交换 k ( k>1 ) 次的方案都可以转换成前面的数先交换 k-1 次,再由新来的数交换一次。所以就能很方便地dp了。

还可以从逆序对的角度考虑第一问、从斯特林数的角度考虑第二问。反正式子是一样的。

#include
#include
#include
#include
#define ll long longusing namespace std;const int N=3005,mod=1e9+7;int n,k,dp[2][N],c[2][N],ans,u,v;int main(){ scanf("%d%d",&n,&k); dp[1][0]=1; for(int i=0;i<=k;i++) c[1][i]=1; u=0;v=1; for(int i=2;i<=n;i++) { for(int j=0;j<=k;j++) { dp[u][j]=(c[v][j]-(j-i>=0?c[v][j-i]:0)+mod)%mod; c[u][j]=(dp[u][j]+(j?c[u][j-1]:0))%mod; } u=!u;v=!v; } for(int i=k;i>=0;i-=2) (ans+=dp[v][i])%=mod; printf("%d ",ans); ans=0; u=0;v=1; memset(dp[1],0,sizeof dp[1]); dp[1][0]=1; for(int i=2;i<=n;i++) { for(int j=0;j<=k;j++) dp[u][j]=(dp[v][j]+(j?(ll)dp[v][j-1]*(i-1)%mod:0))%mod; u=!u;v=!v; } for(int i=0;i<=k;i++) (ans+=dp[v][i])%=mod; printf("%d\n",ans); return 0;}

 

转载于:https://www.cnblogs.com/Narh/p/9606366.html

你可能感兴趣的文章
Caffe + Ubuntu 14.04 64bit + CUDA 6.5 配置说明2
查看>>
javaScript基础练习题-下拉框制作
查看>>
基于 OAuth 安全协议的 Java 应用编程1
查看>>
使用Golang利用ectd实现一个分布式锁
查看>>
javaweb学习总结五(内省、beanUtils工具包)
查看>>
An easy to use android color picker library
查看>>
iOS10全新推送功能的实现
查看>>
C#中容易被忽视的细节整理
查看>>
php内核分析(二)-ZTS和zend_try
查看>>
获取form对象
查看>>
不确定人数的抽奖方法
查看>>
win7 windows server 2008R2下 https SSL证书安装的搭配(搭配https ssl本地测试环境)
查看>>
sh脚本——#!/bin/bash
查看>>
MYSQL-innodb性能优化几个点
查看>>
什么是Mixin模式:带实现的协议
查看>>
Oracle SID爆破工具SidGuess
查看>>
escape、encodeURI以及encodeURIComponent
查看>>
UIView加入手势 然后UITableView 加入进这个View 导致UITableView 的单元格点击事件无效...
查看>>
Vertex and FragmentShader顶点与片段着色器
查看>>
.Net中的AOP系列之《将AOP作为架构工具》
查看>>