日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Acwing 216. Rainbow的信号

發布時間:2023/12/3 编程问答 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Acwing 216. Rainbow的信号 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

Acwing 216. Rainbow的信號

題意:

給你n個數,在這n個數中,等概率地選取兩個數l,r,如果l>r,則交換l,r
把信號中的第 l 個數到第 r 個數取出來,構成一個數列 P。

A 部分對話的密碼是數列 P 的 xor 和的數學期望值,xor 和就是數列 P 中各個數異或之后得到的數; xor 和的期望就是對于所有可能選取的 l、r,所得到的數列的 xor 和的平均數。

B 部分對話的密碼是數列 P 的 and 和的期望,定義類似于 xor 和。

C 部分對話的密碼是數列 P 的 or 和的期望,定義類似于 xor 和。

題解:

參考題解
按位來計算答案。枚舉二進制下的每一位,因為數<109,說明最多30位
對于每一位(這里指的是二進制數位),枚舉1到n每個數,把當前枚舉的第k個數當作是范圍的右端點,考慮左端點的取值情況來計算概率
設當前枚舉的數位是k,當前枚舉的是第r個數,當前第r個數的數位的值為v(v只會是0或1)
注意:題目說了當l>r時會交換l和r,所以l和r的取值范圍均為n,所以l = r的概率為1/n ^ 2,其他概率為2/n ^ 2.
xor 和的期望就是對于所有可能選取的 l、r,所得到的數列的 xor 和的平均數。也就是所能取到的值乘以取到的概率
當數位的值v為1時
因為有l = r的情況,所有xor,and,or的答案都要加上該數位的值乘以1/n ^2(如果這是第3位,那就要加上4/n ^2),我們設pos=(該數為的值)/n ^2 = (1<<k)/n ^2

對于or,or是有1則1,而當前v正是1(也就是第r位是1),所以左端點l隨便取(當前不能等于r),所以l的取值概率為(r-1) * pos * 2(別忘乘以2)
對于and,and是全部為1則1,所以我們需要用last[v]表示上一次v出現的位置,last[0]表示上一次0出現的位置,而l的取值范圍是[last[0]+1,r-1],所以概率為(r-1-last[0])* pos * 2

當前數位的值v為0的時候:
and怎么都是0,所以不用考慮
對于or,l的所取的區間中的數位必須出現一個1,last[1]表示上一次1出現的位置,那l區間范圍是[1,last[1]],所以概率就是last[1] * pos * 2

xor單獨討論
對于1到n各個數在第k位上的數位值:

我們現在以1為邊界將區間分段:

每一段內有且只有一個1(r所在的那一段暫不考慮),異或0對xor沒有影響,而每異或一次1,xor的值就會發生反轉,所以我們用c1表示奇數區間包含的值的個數,c2表示偶數區間包含的值的個數
如果r為1,那么l位于偶數區間的話,答案異或為1,也就是l有c1個取值可能。如果r為0,那么l就有c2個取值可能(代碼中實現c1和c2的方法很妙)
詳細可以看代碼diamond

代碼:

#include<bits/stdc++.h> using namespace std;int read() {int x=0,f=1;char ch=getchar();while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar();}while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar();}return x*f; }const int maxn=1e5+5; int n,c1,c2; int w[maxn],p[maxn],last[2]; double ansxor,ansand,ansor;void solve(int k) {c1=c2=0;last[0]=last[1]=0;double pos=(double)(1<<k)/n/n;//當前數位的實際值/n方的概率for(int r=1;r<=n;r++){int v=((w[r]>>k)&1);if(v){ansxor+=pos;ansand+=pos;ansor+=pos;}if(v){ansor+=pos*(r-1)*2;ansand+=pos*(r-1-last[0])*2;ansxor+=pos*c1*2;}else {ansor+=pos*last[1]*2;ansxor+=pos*c2*2;}++c1;if(v) swap(c1,c2); //到了新的區間,就開始另一個變量開始計數 last[v]=r;} }int main() {n=read();for(int i=1;i<=n;i++) w[i]=read();for(int i=0;i<=30;i++) solve(i);printf("%.3lf %.3lf %.3lf",ansxor,ansand,ansor);return 0; }

總結

以上是生活随笔為你收集整理的Acwing 216. Rainbow的信号的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。