zoukankan      html  css  js  c++  java
  • 某dp题2

    P2401 不等数列

    题目描述

    将1到n任意排列,然后在排列的每两个数之间根据他们的大小关系插入“>”和“<”。问在所有排列中,有多少个排列恰好有k个“<”。答案对2015取模。
    注:1~n的排列指的是1~n这n个数各出现且仅出现一次的数列。

    输入输出格式

    输入格式:

    第一行2个整数n,k。

    输出格式:

    一个整数表示答案。

    输入输出样例

    输入样例#1:

    5 2

    输出样例#1:

    66

    说明

    对于30%的数据:n <= 10
    对于100%的数据:k < n <= 1000

    这个是一个比较那啥的递推(dp)做法
    具体就是考虑一个(1-n)自然数的排列
    然后其中每两个相邻的数之间存在一定的大小关系
    然后考虑下一个数:(n+1)
    那么他比数列中所有的数都大

    如果我们将这个(n+1)插入到数列中的某个位置
    如果将其插入到产生<关系的两侧
    那么产生的<关系的数量将不会改变
    那么所有的<两端一共只有j+1个位置

    同样
    如果将n+1插入到一个>关系的两侧,会增加一个<关系
    所有的>关系的两侧只有i-j个位置

    那么根据这个关系来递推答案
    设f[i][j]表示在(1-i)的所有排列中,有k个<关系的排列有多少个
    那么递推式

    [f_{ij}=(j+1) imes f_{i-1 j}+(i-j) imes f_{i-1j-1} ]

    所以

    [f(i,j) = egin{cases} 1 & mbox{i=0, j=0} \ (j+1) imes f(i-1,j)+(i-j) imes f(i-1,j-1)& mbox{j<i} end{cases} ]

    #include<iostream>
    #include<cstdio>
    #define N 15
    using namespace std;
    
    int f[N][N];
    
    int n,k;
    
    int main(){
    	cin>>n>>k;
    	for(int i=1;i<=n;++i)
    		f[i][0]=1;
    	for(int i=2;i<=n;++i)
    		for(int j=1;j<=min(i-1,k);++i)
    			f[i][j]=((j+1)*f[i-1][j]+(i-j)*f[i-1][j-1])%2015;
    	printf("%d",f[n][k]%2015);
    	return 0;
    }
    
  • 相关阅读:
    构建之法:第二次心得
    构建之法:第一次心得
    tomcat配置限制ip和建立图片服务器
    tomcat8.5优化配置
    java 操作 csv文件
    jsoup教学系列
    (转)js实现倒计时效果(年月日时分秒)
    本地启动tomcat的时候报java.util.concurrent.ExecutionException: java.lang.OutOfMemoryError: PermGen space
    使用mybatis执行oracle存储过程
    java 获取web登录者的ip地址
  • 原文地址:https://www.cnblogs.com/qdscwyy/p/7809306.html
Copyright © 2011-2022 走看看