首页 > 代码库 > BZOJ 2431: [HAOI2009]逆序对数列【dp】

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

Description

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

 

Input

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

 

 

 

Output

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

 

 

 

 

Sample Input样例输入

  4 1


Sample Output样例输出

3

样例说明:

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



测试数据范围

30%的数据  n<=12

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

 

Source

Day1

思路:dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+...+dp[i-1][j-i+1] 很好想的DP,但是一开始O(n^3)竟然报WA!!!!

查了N久终于发现是T 了  TT 记录前缀和就A了

 

 

#include<cstdio>

#include<string.h>

#include<iostream>

#include<algorithm>

#define maxn 400009

#define LL long long

using namespace std;

//dp[i][j]=dp[i-1][j]+dp[i-1][j-1]+...+dp[i-1][j-i+1]

long long dp[1500][1500],sum[1500];

int main()

{

    int n,k;

    scanf("%d%d",&n,&k);

    dp[0][0]=1;

    for(int i=1;i<=n;i++)

    {

        sum[0]=dp[i-1][0];

        for(int j=1;j<=k;j++)sum[j]=sum[j-1]+dp[i-1][j];

        for(int j=0;j<=k;j++)

        {

            dp[i][j]=(sum[j]-sum[j-(i-1)-1])%10000;

            while(dp[i][j]<0)dp[i][j]+=10000;

        }

    }

    printf("%lld\n",dp[n][k]);

    return 0;

}

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