• [HAOI2009] 逆序对数列


    观察数据范围我们发现可以用DP来做这个题qwq,因为它每一位往上填的时候,无论怎么填,总可以从前面的状态转移过来。

    而且题目保证了是从1-n的自然数,所以不存在相同数字的情况。

    我们设计状态(dp[i][j])为长度为i的序列(也就是前(i)个自然数)排成的序列中逆序对数量为(j)的答案个数。

    之后的转移就是往原先的序列中塞下一个数,填的位置不同自然增加的逆序对数量不一样,但是显然增加的数量只能在(0)({i-1})中。

    首先我们可以考虑暴力的(n^3)做法。

    转移方程:

    [dp[i][j]=sum_{k=0}^{max(j-i+1,0)}dp[i-1][k] ]

    试了试竟然有90分???

    但是显然1000的数据不是让我们用(n^3)闹着玩的。所以我们要试图将它优化到(n^2)。这个优化很容易,打个表我们稍加思考就可以发现,每次加的数有重复,而且是以前缀和的形式出现的。所以我们直接记录前缀和做优化就可以省略掉k的遍历了。

    (sum[i][j])来记录前i个数前j个逆序的答案个数。。。。就行了吧qwq

    代码如下。

    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #define mod 10000
    using namespace std;
    int n,k;
    int dp[1010][1010],sum[1010][1010];
    int main()
    {
    	scanf("%d%d",&n,&k);
    	for(int i=0;i<=n;i++) dp[i][0]=1,sum[i][0]=1;
      	sum[0][0]=0;
    	for(int i=1;i<=n;i++)
    	{
    		for(int j=1;j<=k;j++)
    		{
    			dp[i][j]=(dp[i][j]+sum[i-1][j])%mod;
    			if(j-i>=0) dp[i][j]=(dp[i][j]+mod-sum[i-1][j-i])%mod;
    			sum[i][j]=(sum[i][j-1]+dp[i][j])%mod;
    		}
    	}
    	printf("%d
    ",dp[n][k]);
    	return 0;
    } 
    
  • 相关阅读:
    Python中的分支条件结构
    Python中常用的数据类型转换
    Python中的运算符
    Python中的输入和输出
    信息收集之zoomeye
    信息收集之censys
    linux权限管理
    linux软件安装管理
    Linux网络管理
    磁盘管理与用户管理
  • 原文地址:https://www.cnblogs.com/fengxunling/p/9834917.html
Copyright © 2020-2023  润新知