校內模擬 記憶(狀壓DP)

2021-09-27 13:09:55 字數 1889 閱讀 7713

考場想到了正解,然後被卡快取記憶體,gg

乙個顯然的轉化就是設e

ie_i

ei​表示朋友選擇第i

ii個串的時候的期望操作次數。則答案就是所有e

ie_i

ei​的平均值。

首先考慮乙個o(n

l2l)

o(nl2^l)

o(nl2l

)的暴力,對於每個串,列舉所有其他串看有多少個位置相同,則我們能夠知道選取哪些位置集合不能辨別這個串,則這些集合的任意乙個子集都不能辨別這個串,則我們直接考慮選擇某乙個位置之後選取狀態s→t

s\rightarrow t

s→t,其中s

ss是非法狀態,t

tt是合法狀態。

我們突然發現如果乙個集合無法辨別某個子串,則任意子集都無法辨別。

設c nt

[s

]cnt[s]

cnt[s]

表示s

ss狀態無法分辨的子串個數,則cnt

[s]−

cnt[

t]

cnt[s]-cnt[t]

cnt[s]

−cnt

[t]就能夠表示在s→t

s\rightarrow t

s→t這一步中被辨別的子串個數,也就可以算貢獻了。

處理請參考**裡面的注釋,對,就是考場上寫的注釋

**:

#include

#define ll long long

#define re register

#define cs const

int n,l,s;

ll match[22]

[513];

// match[i][c] 第 i 位為 c 的字串集合

ll same[

1<<20|

1][52

];// same[s][i] 詢問狀態為 s 的時候無法與 i 區分的串的集合

short cnt[

1<<20|

1];// cnt[s] 詢問狀態為 s 的情況下無法區分的串的數量

//long double dp[1<<20|1]// 詢問到 s 狀態的概率。這個好像是組合數,1/

long

double c[22]

;short ctz[

1<<20|

1],pc[

1<<20|

1];// ctz popcount

inline

void

init()

for(

int re i=

0;i<=l;

++i)c[i]

=c[l]

[i];

for(

int re i=

1;i++i)ctz[i]

=(i&1)

?0:(ctz[i>>1]

+1),pc[i]

=pc[i>>1]

+(i&1)

;}#ifdef zxyoi

#undef zxyoi

#endif

char s[52]

[22];

#define lb(x) ((x)&-(x))

signed

main()

cnt[0]

=n;for

(int re s=

1;s++s)

}long

double ans=0;

for(

int re s=

1;s++s)

printf

("%.10f",(

double

)(ans/n));

return0;

}

2018 10 17 校內模擬 管道(狀壓DP)

簡直有毒,出題人還一本正經的說 我覺得沒有去年noi pd2t 2noipd2t2 noipd2 t2難啊 我只想說,去年d2t 2d2t2 d2t2 的轉移方程那裡有這麼鬼畜。首先利用兩個陣列f,d pf textdp f,dp 來進行狀態轉移。定義如下fi,staf fi,sta 表示不向點i ...

校內模擬 排列(狀壓DP)(矩陣快速冪)

簡要題意 統計有多少個不同的 n nn 排列滿足 pi i k p i i leq k pi i k k 4 k leq 4 k 4 容易發現當前位置選擇哪乙個只會影響到後面 k kk 個位置。k kk 本身非常小,狀壓即可。容易發現轉移和當前是第幾位無關,只和狀態有關,而且是線性,寫成矩陣然後快速...

NOIP模擬 乘積(狀壓DP)

題意 選擇不超過 k 個 n以內的正整數撐起來,使得乘積是乙個無平方因子數 不能夠被任意乙個質數的平方整除 一共有多少種取法?n 500,k 500 題解 首先,很容易想到狀壓,壓縮當前已經選過某質數的狀態。對於質數個數小於 20 可以直接過,但是問題是現在 n 以內的質數個數很多,無法壓縮。考慮狀...