传呼机密码解密:XOR、AND、OR和的期望值计算
Freda发明了传呼机之后,rainbow进一步改进了传呼机发送信息所使用的信号。由于现在是数字、信息时代,rainbow发明的信号用N个自然数表示。为了避免两个人的对话被大坏蛋VariantF偷听T_T,rainbow把对话分成A、B、C三部分,分别用a、b、c三个密码加密。现在Freda接到了rainbow的信息,她的首要工作就是解密。Freda了解到,这三部分的密码计算方式如下:
在1~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和。
输入
第一行一个正整数N。
第二行N个自然数,表示Freda接到的信号。
输出
一行三个实数,分别表示xor和、and和、or和的期望,四舍五入保留3位小数,相邻两个实数之间用一个空格隔开。
样例输入
样例输入1 2 4 5
样例输入2 3 1 0 1
样例输出
样例输出1 2.750 4.250 4.750
样例输出2 0.667 0.222 0.889
样例解释
样例1共包含四种可能的l、r:
l, r xor和 and和 or和 1,1 4 4 4 1,2 1 4 5 2,1 1 4 5 2,2 5 5 5
以上每一对l、r出现的概率均相同,因此分别对xor和、and和、or和取平均数就是数学期望值。
C++内容:
#include <iostream>
#include <vector>
#include <algorithm>
#include <cmath>
using namespace std;
int main() {
int N;
cin >> N;
vector<int> signal(N);
for (int i = 0; i < N; ++i) {
cin >> signal[i];
}
double xorSum = 0.0;
double andSum = 0.0;
double orSum = 0.0;
for (int l = 0; l < N; ++l) {
for (int r = l; r < N; ++r) {
vector<int> subSignal(signal.begin() + l, signal.begin() + r + 1);
int xorResult = subSignal[0];
int andResult = subSignal[0];
int orResult = subSignal[0];
for (int i = 1; i < subSignal.size(); ++i) {
xorResult ^= subSignal[i];
andResult &= subSignal[i];
orResult |= subSignal[i];
}
xorSum += xorResult;
andSum += andResult;
orSum += orResult;
}
}
double xorExpectation = xorSum / (N * (N + 1) / 2);
double andExpectation = andSum / (N * (N + 1) / 2);
double orExpectation = orSum / (N * (N + 1) / 2);
cout << fixed << setprecision(3) << xorExpectation << " " << andExpectation << " " << orExpectation << endl;
return 0;
}
原文地址: https://www.cveoy.top/t/topic/pigp 著作权归作者所有。请勿转载和采集!