【BZOJ2431】【HAOI2009】逆序对数列

博客探讨了如何解决BZOJ2431和HAOI2009比赛中的逆序对数列问题。主要内容涉及输入输出格式及样例,并指出需要计算满足条件的数列数量模10000的结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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;
100%的数据 n<=1000,k<=1000
题解
前缀和优化dp.
由于逆序对个数与每个数位置有关,所以我开始时想dp[i][j]表示第i个位置放j这个数的最优解。但没办法转移。。
后来看题解知道了前缀和优化dp的东西,dp[i]][j]表示数列中有i-1个数,把第i个数放进去逆序对为j的方案数,由于i>前面的所有数,所以枚举原来i-1时逆序对数k(max(j-i+1,0),j)时i-1-k就是增加的逆序对个数,
所以dp[i][j]=sigmadp[i-1][k]。由于是连续区间的和,所以可以用前缀和优化把三维变成二维,当j-i小于0时i-1的逆序对数可以是0,就直接是一个前缀和,当j-i>=0时就是中间一段区间的和了,所以要减去dp[i-1][j-i]再赋值;最后输出dp[n][k]就好了。
#include<iostream>
#include<cstdio>
#include<algorithm>
using namespace std;
const int mod=10000;
int dp[1005][1005];
int main(){
	int n,k,sum;
	scanf("%d%d",&n,&k);
	dp[0][0]=1;
	for(int i=1;i<=n;i++){
		sum=0;
		for(int j=0;j<=k;j++){
			if(j-i>=0) sum=(sum-dp[i-1][j-i]+mod)%mod;
			sum=(sum+dp[i-1][j])%mod;
			dp[i][j]=sum;
		}
	}
	printf("%d\n",dp[n][k]);
	
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值