[HAOI2009]逆序对数列
题目描述
对于一个数列{ai},如果有i<j且ai>aj,那么我们称ai与aj为一对逆序对数。若对于任意一个由1~n自然数组成的数列,可以很容易求出有多少个逆序对数。那么逆序对数为k的这样自然数数列到底有多少个?
输入输出格式
输入格式:第一行为两个整数n,k。
输出格式:写入一个整数,表示符合条件的数列个数,由于这个数可能很大,你只需输出该数对10000求余数后的结果。
输入输出样例
输入样例#1:
4 1
输出样例#1:
3
说明
样例说明:
下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;
测试数据范围
30%的数据 n<=12
100%的数据 n<=1000,k<=1000
日常刷水题.....
显然看数据,f[i][j]表示1~i有j个逆序对的方案数
因为i只能增加0~i-1个逆序对,分别对应放在i-1后面和1前面的情况
那么得到f[i][j]=∑f[i-1][k] max(j-i+1,0)<=k<=j
算法是O(n^3)
用前缀和优化到O(n^2)
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 long long f[1001][1001],sum[1001][1001]; 7 int n,k; 8 int main() 9 {int i,j; 10 cin>>n>>k; 11 for (i=1;i<=n;i++) 12 { 13 f[i][0]=1; 14 sum[i][0]=1; 15 for (j=1;j<=k;j++) 16 { 17 if (j-i>=0) 18 f[i][j]=(sum[i-1][j]-sum[i-1][j-i]+10000)%10000; 19 else f[i][j]=sum[i-1][j]; 20 sum[i][j]=f[i][j]; 21 sum[i][j]+=sum[i][j-1]; 22 sum[i][j]%=10000; 23 } 24 } 25 cout<<f[n][k]%10000<<endl; 26 }