zoukankan      html  css  js  c++  java
  • Jzoj5235 好的排列

    对于一个1->n的排列 ,定义A中的一个位置i是好的,当且仅当Ai-1>Ai 或者Ai+1>Ai。对于一个排列A,假如有不少于k个位置是好的,那么称A是一个好的排列。

    现在有q个询问,每个询问给定n,k,问有多少排列是好的。答案对10^9+7取模。

    显然是计数类dp,我们设f[i][j]表示对于一个1->i的排列,好的位置有j个的情况

    考虑转移,显然f[i][j]->f[i+1][k]相当于插入一个i+1

    那么我们考虑对j的影响,显然f[i][j]只能转移到f[i+1][j]或者f[i][j],因为这取决于你将i+1放在哪个位置上

    如果放在一个不是好位置的两边,那么j就会+1,否则j不变,而且显然,不好的位置一定不连续(显然)

    那么转移就十分简单了,参考code

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define M 1000000007
    #define L long long
    using namespace std;
    void ad(int& x,L y){ x=(y+x)%M; }
    int f[3010][3010]={0},s[3010][3010]={0},n;
    int main(){
    	freopen("permutation.in","r",stdin);
    	freopen("permutation.out","w",stdout);
    	f[1][0]=1; f[2][1]=2; 
    	f[3][1]=2; f[3][2]=4;
    	for(int i=3;i<3000;++i){
    		L pi=(i+1)-2,pj=2;
    		for(int j=i-1;pi>=0;--j){
    			ad(f[i+1][j],f[i][j]*pi);
    			ad(f[i+1][j+1],f[i][j]*pj);
    			pi-=2; pj+=2;
    		}
    	}
    	for(int i=1;i<=3000;++i)
    		for(int j=i-1;~j;--j){
    			s[i][j]=s[i][j+1];
    			ad(s[i][j],f[i][j]);
    		}
    	scanf("%d",&n);
    	for(int x,y,i=0;i<n;++i){
    		scanf("%d%d",&x,&y);
    		printf("%d
    ",s[x][y]);
    	}
    }

  • 相关阅读:
    selenium 安装
    创建项目/执行
    mysql远程访问
    如何通过批处理文件直接运行python代码
    python中通过字典实现函数指针
    装饰器
    正则表达式学习笔记
    Jupyter使用
    【数学】一张通往数学世界的地图-阅读笔记
    【算法导论】二叉搜索树的删除除操作
  • 原文地址:https://www.cnblogs.com/Extended-Ash/p/7846019.html
Copyright © 2011-2022 走看看