• BZOJ 2431 [HAOI2009]逆序对数列:dp 逆序对


    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2431

    题意:

      给定n,k,问你有多少个由1~n组成的排列,使得逆序对个数恰好为k个。

    题解:

      表示状态:

        dp[i][j] = num of sequences

        i:已经用了1~i之间的数(在这一步放了数字i)

        j:逆序对个数为j

      找出答案:

        ans = dp[n][k]

      如何转移:

        在当前这一步要放数字i。

        所以要将i插入一个由1~i-1组成的排列中。

        若将i插入位置x(0 <= x <= i-1),则新添的逆序对个数为x。

        所以:

          dp[i][j] = ∑ dp[i-1][j-x]

        即:

          dp[i][j] = ∑ dp[i-1][j-i+1 to j]

        由于裸dp复杂度为O(N^3) = O(10^9),所以加一个前缀和优化。

      边界条件:

        dp[1][0] = 1

        others = 0

    AC Code:

     1 // state expression:
     2 // dp[i][j] = num of sequences
     3 // i: considered number i
     4 // j: there is j inversion pairs
     5 //
     6 // find the answer:
     7 // ans = dp[n][k]
     8 //
     9 // transferring:
    10 // dp[i][j] = sigma dp[i-1][j-i+1 to j]
    11 //
    12 // boundary:
    13 // dp[1][0] = 1
    14 #include <iostream>
    15 #include <stdio.h>
    16 #include <string.h>
    17 #define MAX_N 1005
    18 #define MAX_K 1005
    19 #define MOD 10000
    20 
    21 using namespace std;
    22 
    23 int n,t;
    24 int dp[MAX_N][MAX_K];
    25 int sum[MAX_N][MAX_K];
    26 
    27 void read()
    28 {
    29     cin>>n>>t;
    30 }
    31 
    32 void update_sum(int i,int j,int a)
    33 {
    34     if(j==0) sum[i][j]=a;
    35     else sum[i][j]=(sum[i][j-1]+a)%MOD;
    36 }
    37 
    38 int query_sum(int i,int x,int y)
    39 {
    40     if(x==0) return sum[i][y];
    41     else return ((sum[i][y]-sum[i][x-1])%MOD+MOD)%MOD;
    42 }
    43 
    44 void solve()
    45 {
    46     memset(dp,0,sizeof(dp));
    47     memset(sum,0,sizeof(sum));
    48     dp[1][0]=1;
    49     for(int i=0;i<=t;i++)
    50     {
    51         sum[1][i]=1;
    52     }
    53     for(int i=2;i<=n;i++)
    54     {
    55         for(int j=0;j<=t;j++)
    56         {
    57             dp[i][j]=query_sum(i-1,max(0,j-i+1),j);
    58             update_sum(i,j,dp[i][j]);
    59         }
    60     }
    61 }
    62 
    63 void print()
    64 {
    65     cout<<dp[n][t]<<endl;
    66 }
    67 
    68 int main()
    69 {
    70     read();
    71     solve();
    72     print();
    73 }
  • 相关阅读:
    插入节点方法appendChild和insertBefore
    大河剧《独眼龙政宗》梵天丸喜多对话台词
    ie6绝对定位层元素消失
    strtok函数相关理解
    [创建型模式] Prototype
    用C实现旋转棒进度条指示器
    使用不规则数组(ragged array)和agetline()将整个文件读入内存
    [创建型模式] AbstractFactory
    xcode_4_and_ios_sdk_4.3__final相关下载地址
    [创建型模式] Singleton
  • 原文地址:https://www.cnblogs.com/Leohh/p/7699900.html
Copyright © 2020-2023  润新知