bzoj2431 [HAOI2009]逆序对数列
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
样例说明:
下列3个数列逆序对数都为1;分别是1 2 4 3 ;1 3 2 4 ;2 1 3 4;
100%的数据 n<=1000,k<=1000
正解:$dp$。
考虑枚举$i$这个数放在序列的哪个位置,如果放在第$j$位前面,则会产生$i-j$的贡献。
那么$f[i][j]$表示前$i$个数,逆序对数为$j$的方案数,$f[i][j]=\sum_{}{}f[i-1][j-k]$。
然后似乎是个前缀和优化就没了,不过我没看出来,打了个表找规律。。
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <cstring> 5 #include <cstdlib> 6 #include <cstdio> 7 #include <vector> 8 #include <cmath> 9 #include <queue> 10 #include <stack> 11 #include <map> 12 #include <set> 13 #define inf (1<<30) 14 #define rhl (10000) 15 #define il inline 16 #define RG register 17 #define ll long long 18 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 19 20 using namespace std; 21 22 int f[1010][1010],n,k; 23 24 il int gi(){ 25 RG int x=0,q=1; RG char ch=getchar(); 26 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 27 if (ch=='-') q=-1,ch=getchar(); 28 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 29 return q*x; 30 } 31 32 il void work(){ 33 n=gi(),k=gi(),f[0][0]=1; 34 for (RG int i=1;i<=n;++i) 35 for (RG int j=0;j<=k;++j) 36 f[i][j]=(f[i-1][j]+f[i][j-1]-(j>=i)*f[i-1][j-i]+rhl)%rhl; 37 printf("%d\n",f[n][k]); return; 38 } 39 40 int main(){ 41 File("seq"); 42 work(); 43 return 0; 44 }