[luogu2513 HAOI2009] 逆序對數列 (計數dp)
阿新 • • 發佈:2018-06-05
class Go 數列 += n) #define 100% ems sin
題目描述
對於一個數列{ai},如果有i
輸入輸出格式
輸入格式:
第一行為兩個整數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] 表示i的排列有j個逆序對數的情況數
依次插入1,2,3,4......,n
插入第i個數時:
當插在0位置時逆序對增加(i-1)組,
當插在1位置時逆序對增加(i-2)組,
......
跟據以上想法推出出動規方程:
F(i,1,n) F(j,1,k) F(l,max(1,i-j),i)
f[i][j]+=f[i-1][j-(i-l)];
n^3過不了,用下前綴和優化即可
code:
//By Menteur_Hxy
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
#include <map>
#include <vector>
#include <queue>
#include <set>
#include <ctime>
#define M(a,b) memset(a,(b),sizeof(a))
#define F(i,a,b) for(register int i=(a);i<=(b);i++)
#define LL long long
using namespace std;
inline LL rd() {
LL x=0,fla=1; char c=‘ ‘;
while(c>‘9‘|| c<‘0‘) {if(c==‘-‘) fla=-fla; c=getchar();}
while(c<=‘9‘ && c>=‘0‘ ) x=x*10+c-‘0‘,c=getchar();
return x*fla;
}
inline void out(LL x){
int a[25],wei=0;
if(x<0) putchar(‘-‘),x=-x;
for(;x;x/=10) a[++wei]=x%10;
if(wei==0){ puts("0"); return;}
for(int j=wei;j>=1;--j) putchar(‘0‘+a[j]);
putchar(‘\n‘);
}
const int MOD=10000;
const int N=1010;
const int INF=0x3f3f3f3f;
int n,k;
int f[N][N];
int main() {
n=rd(),k=rd();
f[1][0]=1;
F(i,2,n) {
LL sum=0;
F(j,0,k) {
(sum+=f[i-1][j])%MOD;
f[i][j]=sum%MOD;
if(j-i+1>=0) ((sum-=f[i-1][j-i+1])+MOD)%MOD;
}
}
out(f[n][k]);
return 0;
}
[luogu2513 HAOI2009] 逆序對數列 (計數dp)