PKUSC2018 最大字首和(狀壓DP)

2022-05-11 03:53:00 字數 1399 閱讀 8481

題目大意:求給定的 $n$ 個數的所有排列的最大字首和(不能為空)之和對 $10^9+7$ 取模的值。

$1\le n\le 20,1\le\sum|a_i|\le 10^9$。

神級dp。雜題選講的神級毒瘤講題人cdw講的。

考慮乙個集合 $s$ 能作為最大字首和出現的方案數。(即貢獻係數)

發現前 $|s|$ 個數滿足最大字首和是整個序列,後 $n-|s|$ 個數滿足最大字首和 $<0$。(雖然 $\le 0$ 也行,但為了避免重複統計就要 $<0$)

設 $f[s]$ 為在 $s$ 的所有排列中,最大字首和 $<0$ 的個數。

設 $g[s]$ 為在 $s$ 的所有排列中,最大字首和 $=sum[s]$ 的個數。($sum$ 是和)

$f[s]=\begin0&sum[s]\ge 0\\ \sum\limits_f[s-\]&sum[s]<0\end$

初始 $f[0]=1$。

解釋一下,如果 $sum[s]\ge 0$,那麼最大字首和不會小於 $0$。否則列舉最後乙個數,當且僅當前面的最大字首和 $<0$ (或者前面沒有數,所以 $f[0]=1$)且 $sum[s]<0$ 時才可以。第二個條件已經保證滿足了。

$g[s]\rightarrow g[s+(1初始 $g[\]=1$。

解釋一下,考慮從已有狀態擴充套件,列舉在 $s$ 前加乙個數 $i$,當且僅當 $s$ 最大字首和是自己時,新序列最大字首和才是自己。、

答案為 $\sum sum[s]g[s]f[u-s]$。

時間複雜度 $o(n2^n)$。

#includeusing

namespace

std;

typedef

long

long

ll;const

int mod=998244353

;#define for(i,a,b) for(int i=(a);i<=(b);i++)

#define rof(i,a,b) for(int i=(a);i>=(b);i--)

#define mem(x,v) memset(x,v,sizeof(x))inline

intread()

int n,a[22],ans,f[1111111],g[1111111

];ll s[

1111111

];int

main()

else for(j,0,n-1) if((i>>j)&1) f[i]=(f[i]+f[i^(1

}for(i,

0,(1

<1) ans=(ans+1ll*(s[i]+mod)%mod*g[i]%mod*f[((1

<1)^i])%mod;

printf(

"%d\n

",ans);

}

view code

PKUSC2018 最大字首和

看資料範圍認解法 首先在每種情況出現概率相同的情況下,期望 times 方案數 權值和 即題意就是讓你求所有排列的最大字首和的總和 我們可以列舉哪些數是最大字首,顯然這些數內部任意交換順序 其它數內部任意交換順序 都不會改變這個最大字首。一些數要排到前面去成為最大字首,條件是該字首除整段外的所有字尾...

PKUSC2018 最大字首和(狀壓dp)

狀壓好題啊。一眼看出時間複雜度 o n2 n 然後開始想正解。然後設 dp i 為字首狀態為 i 時的方案數,所以這時候 sum i 一定是單峰的。可以推導出 1 leq j i 那麼我們相當於求兩個序列拼湊起來,乙個序列字首和除第一項始終 geq 0 因為 sum i sum 1 不包括第一項,但...

PKUSC 2018 真實排名

戳我 我們將現在所要進行的數設為 now 我們分情況討論一下 他自己不翻倍 他自己翻倍 我們首先來看看 1 操作 如果要滿足他對排名沒有影響,那麼不能進行翻倍的數只有 lceil frac rceil,now 我考場上不知道在幹嗎,寫的是能進行翻倍的數,麻煩好多,常數也大 我們假設這一段為 cnt ...