zoukankan      html  css  js  c++  java
  • [HAOI2009]逆序对数列

    题目描述

    对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数。若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数。那么逆序对数为k的这样自然数数列到底有多少个?

    输入输出格式

    输入格式:

    第一行为两个整数n,k。

    输出格式:

    写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果。

    输入输出样例

    输入样例#1:
    4 1
    输出样例#1:
    3

    说明

    样例说明:

    下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;

    测试数据范围

    30%的数据 n<=12

    100%的数据 n<=1000,k<=1000

    题解:

    算是比较好想吧.

    如果dp每一位,显然不好记录状态,那么就按填数的顺序枚(从小到大一个个填)

    f[i][j]表示已经填了小于等于i的数,产生的逆序对数量为j的方案数

    显然现在插入的i比以前都大,那么可以产生[0,i-1]个逆序对

    于是就可以枚举产生的逆序对数量k开始推了

    f[i][j]+=f[i-1][j-k]

    而且j-k是连续一段的和,那么可以用前缀和O(1)算出

     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 #define RG register
     8 using namespace std;
     9 typedef long long ll;
    10 const int N=1005,mod=10000;
    11 int f[N][N];ll sum[N];
    12 void work()
    13 {
    14     int n,m;
    15     scanf("%d%d",&n,&m);
    16      for(int j=1;j<=m+1;j++)sum[j]=1;
    17     for(RG int i=2;i<=n;i++){
    18          for(RG int j=0,tmp;j<=m;j++){
    19              if(j-i+1>0)tmp=j-i+1;
    20              else tmp=0;
    21              f[i][j]+=sum[j+1]-sum[tmp];
    22              f[i][j]%=mod;
    23          }
    24          for(int j=1;j<=m+1;j++){
    25              sum[j]=sum[j-1]+f[i][j-1];
    26          }
    27     }
    28     printf("%d
    ",f[n][m]);
    29 }
    30 int main()
    31 {
    32     work();
    33     return 0;
    34 }
  • 相关阅读:
    linux常用命令全拼
    foxmail怎么设置个性签名
    linux下kerberos教程
    linux解压war包的命令
    Jenkins部署Web项目到远程tomcat(通过jenkins插件)
    Shell特殊变量:Shell $0, $#, $*, $@, $?, $$和命令行参数
    windows下命令行终端使用rz上传文件参数详解
    svn 命令行下常用的几个命令
    性能测试指标及解释
    性能测试的分类及各分类理解
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7291416.html
Copyright © 2011-2022 走看看