題目大意:求給定的 $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)$。
#includeusingview codenamespace
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);
}
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 ...