BZOJ4361 isn(動態規劃,容斥)

2021-08-21 10:08:56 字數 1997 閱讀 5380

bzoj

首先我們如果確定了乙個不降序列,假設它的長度為

i i

, 那麼可行的方案數為i∗

(n−i

)!' role="presentation">i∗(

n−i)

!i∗(

n−i)

!,但是這樣有一些非法的情況,即刪掉最後乙個數之前已經是有序的了。

那麼設g[i

] g[i

]表示長度為

i i

的不降序列的總數

因為所有長度為

i' role="presentation">i

i的不降序列一定包含在長度為i+

1 i+1

的不降序列之中

如果先構成了乙個長度為i+

1 i+1

的不降序列,再刪掉了一位,那麼這樣是不合法的。

所以長度為

i i

的不降序列的貢獻為: g[

i]∗(

n−i)

!−g[

i+1]

∗(n−

i−1)

!∗(i

+1)' role="presentation">g[i

]∗(n

−i)!

−g[i

+1]∗

(n−i

−1)!

∗(i+

1)g[

i]∗(

n−i)

!−g[

i+1]

∗(n−

i−1)

!∗(i

+1)即先構成了乙個長度為i+

1 i+1

的不降序列,再列舉刪去了哪個數構成了長度為

i i

的不降序列。 至於i

' role="presentation">i

i怎麼算,可以設f[

i][j

] f[i

][j]

表示以i i

結尾,長度為

j' role="presentation">j

j的不降序列的個數 f[

i][j

]=∑f

[k][

j−1]

(a[k

]≤a[

i]) f[i

][j]

=∑f[

k][j

−1](

a[k]

≤a[i

])

樹狀陣列優化一下就好了

時間複雜度o(

n2lo

gn) o(n

2log

n)

#include

#include

#include

#include

#include

#include

using

namespace

std;

#define ll long long

#define rg register

#define max 2002

#define mod 1000000007

inline

int read()

void add(int &x,int y)

int a[max],n,s[max],len;

int f[max][max],g[max];

int c[max],jc[max],ans;

int lb(int x)

void modify(int x,int w)

int getsum(int x)

int main()

}add(ans,g[n]);

for(int i=n-1;i;--i)

add(ans,(1ll*g[i]*jc[n-i]%mod-1ll*g[i+1]*jc[n-i-1]%mod*(i+1)%mod+mod)%mod);

printf("%d\n",ans);

}

bzoj4361 isn(樹狀陣列優化dp 容斥)

time limit 10 sec memory limit 256 mb submit 938 solved 485 submit status discuss 給出乙個長度為n的序列a a1,a2.an 如果序列a不是非降的,你必須從中刪去乙個數,這一操作,直到a非降為止。求有多少種不同的操作方...

BZOJ1037動態規劃

資料範圍很小,可以用4維儲存下前i個男孩j個女孩,從這一位往前的所有點中男 女的差最大為x,女 男為y的方案數 主動遞推 f i 1 j x 1 max y 1 0 f i j x y f i j 1 max x 1 0 y 1 f i j x y 最後答案為 sigma x sigma y f n...

BZOJ1040 騎士(動態規劃)

bzoj 對於每一組厭惡的關係 顯然是連邊操作 如果是一棵樹的話 很顯然的樹型dp 但是,現在相當於有很多個基環 也就是在一棵樹的基礎上再加了一條邊 這個時候怎麼辦,暴力拆掉基環 拆掉任意一條邊 跑兩遍dp 計算出強制不選兩個點中某乙個的最大值 此時就是這個基環的最大值 不用拆掉所有的邊,因為只要拆...