• 题解【洛谷P2513/CJOJ1345】[HAOI2009]逆序对数列


    Description

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

    Input

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

    Output

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

    Sample Input

    4 1

    Sample Output

    3

    Hint

    样例说明:
    下列3个数列逆序对数都为1;
    分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;

    测试数据范围
    30%的数据 n<=12
    100%的数据 n<=1000,k<=1000

    Source

    HAOI,分治,递推

    Solution

    考虑DP。

    dp[i][j]表示i的排列中逆序对数为j的方案数。

    考虑i的放置,i为最大值,所以放在i-1个位置都可以计算出对答案的贡献,因此DP递推式为:

    dp[i][j]=Σdp[i-1][k] (j-i+1<=k<=j)

    考虑特殊情况:到i时最多可以贡献i-1对逆序对,所以从dp[0]~dp[j-i+1]这一段不能加!

    但是这个算法要枚举i、j和k,时间复杂度为n^3,绝对TLE,因此考虑前缀和优化。

    Code

     1 #include <bits/stdc++.h>
     2 #define int long long
     3 
     4 using namespace std;
     5 
     6 inline int read()
     7 {
     8     int f = 1, x = 0;
     9     char c = getchar();
    10 
    11     while (c < '0' || c > '9')
    12     {
    13         if (c == '-')
    14             f = -1;
    15         c = getchar();
    16     }
    17 
    18     while (c >= '0' && c <= '9')
    19     {
    20         x = x * 10 + c - '0';
    21         c = getchar();
    22     }
    23 
    24     return f * x;
    25 }
    26 
    27 const int mod = 10000;
    28 
    29 int n, m, dp[1005][1005];
    30 
    31 signed main()
    32 {
    33     n = read(), m = read();
    34 
    35     dp[1][0] = 1;
    36 
    37     for (register int i = 2; i <= n; i++)
    38     {
    39         int sum = 0;
    40 
    41         for (register int j = 0; j <= m; j++)
    42         {
    43             sum = (sum + dp[i - 1][j]) % mod;
    44 
    45             dp[i][j] = sum;
    46 
    47             if (j - i + 1 >= 0)
    48             {
    49                 sum = (sum - dp[i - 1][j - i + 1] + mod) % mod;
    50             }
    51         }
    52     }
    53 
    54     printf("%lld", dp[n][m]);
    55 
    56     return 0;
    57 }
  • 相关阅读:
    [转]Intellij IDEA快捷键与使用小技巧
    Swoole来实现实时异步任务队列
    php 异步执行脚本
    Centos 7 systemctl和防火墙firewalld命令
    tgz的解压
    error: C++ preprocessor "/lib/cpp" fails sanity check错误解决方法
    Linux 命令详解(三)./configure、make、make install 命令
    LNMP, CentOS7.0+Nginx+Mysql5.7+PHP7环境安装
    phpmailer使用qq邮箱、163邮箱成功发送邮件实例代码
    Mibew Messenger (also known as Open Web Messenger)
  • 原文地址:https://www.cnblogs.com/xsl19/p/10519834.html
Copyright © 2020-2023  润新知