Rainbow的訊號 題解報告

2022-04-28 20:51:13 字數 1463 閱讀 8639

題目傳送門

【題目大意】

給定乙個有n個數的數列,在這n個數中等概率的選取兩個數l,r(保證l≤r),組成乙個區間[l,r],求出區間的每個數異或之後的結果,求對於這個數列的異或的期望值(此處定義為所有區間異或的結果的平均數)。類似地還要求出與運算和或運算的期望值。

【思路分析】

這題乍一看有點複雜呀,其實就是乙個披著概率的皮的位運算題。

既然是位運算,那就很簡單啦。因為位運算是不會出現進製的,也就是說每一位之間互不影響,所以就可以拆開之後一位一位地處理。首先把數列a中的每個數都轉成二進位制,然後b[i]表示a[i]第k位的數,此處的k會在程式執行過程中列舉。

然後我們發現對於任意區間,只可能存在兩種情況:長度=1或長度≥2。

分類討論發現,區間長度=1時,期望值就是乘上$\frac$,而區間長度≥2時,期望值就是乘上$\frac$

接下來對於三種運算我們分別分析一下(相對二進位制每一位來說)

1.與運算

根據與運算的特點可知,只要區間內出現了0,那麼整個區間的結果就一定是0

2.或運算

同樣根據特點可知,只要區間內出現了1,那麼整個區間的結果就一定是1

3.異或運算

異或運算比較麻煩,我們需要找到區間內每個1的位置,然後一旦遇到1,結果就會變化(由1變成0或者由0變成1),所以可以以1為分界線把整個區間分割成幾塊,然後再具體處理

為了方便實現,我們列舉右端點,用last[0]和last[1]分別記錄上乙個出現0和1的位置,然後用c1和c2分別記錄當前情況下可以使異或結果為1和0的左端點個數。

這裡要注意一點,當我們列舉到乙個新的右端點的時候,要根據這一點是1或0分類討論,詳見**。

還有乙個要注意的地方就是不能直接/(n*n),而要寫成/n/n,我也不知道為什麼但我就是被這個地方卡了好久,也許是精度問題?qaq

【**實現】

1 #include2

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

3using

namespace

std;

4double

ans_and,ans_or,ans_xor;

5int a[1000002],b[1000002

],n;

6void work(int k),c1=0,c2=0

;8 go(i,1

,n)14

}15 go(i,1,n)

22 ans_xor+=(1

<2.0/n/n*(b[i]?c1:c2);

23 c1++;if

(b[i]) swap(c1,c2);

24 last[b[i]]=i;25}

26}27int

main()

**戳這裡

NOIP2013模擬 Rainbow的訊號

time limits 1000 ms memory limits 131072 kb special judge description freda發明了傳呼機之後,rainbow 進一步改了傳呼機傳送資訊所使用的號。由於現在是數字 資訊時代,rainbow 發明的訊號用 n個自然數表示。為了避免...

NOIP2013模擬 Rainbow的訊號

正解 類數字dp,統計二進位制下0和一的個數,blablabla。具體不懂,要再問問,懂了再更。我們可以考慮二進位制 可以想到,將每一位分別求出,在統計起來就可以了。var n,m,tot0,tot1 int64 i,j,l,k longint ans1,ans2,ans3 int64 a arra...

Luogu 4998 訊號塔 題解報告

給定乙個數軸,以及數軸上的 n 個點 這些點可能坐落在同一座標上 第 i 個點的座標為 a i 現在要在數軸上找 k 個點,第 i 個點的座標為 x i 求這 k 個點到原數軸上 n 個點距離和的最小值,即 min sum sum x i a j 注 n,a i leq 10 6,k leq n 首...