概率,位运算
这次就放两道题目好了
P3908 数列之异或
题目链接
求
1
⨁
2
⨁
3
⨁
⋯
⨁
n
1\bigoplus 2\bigoplus 3\bigoplus \cdots \bigoplus n
1⨁2⨁3⨁⋯⨁n
先打表:
1 1
2 3
3 0
4 4
5 1
6 7
7 0
8 8
9 1
10 11
11 0
12 12
13 1
14 15
15 0
16 16
17 1
18 19
19 0
20 20
稍微打几个出来就已经非常明显了:
S
n
=
{
n
n
≡
0
(
m
o
d
4
)
1
n
≡
1
(
m
o
d
4
)
n
+
1
n
≡
2
(
m
o
d
4
)
0
n
≡
3
(
m
o
d
4
)
S_n = \begin{cases} n &\text{} n\equiv0 \pmod 4 \\ 1 &\text{} n\equiv1 \pmod 4\\ n+1 &\text{} n\equiv2 \pmod 4\\ 0 &\text{} n\equiv3 \pmod 4\\ \end{cases}
Sn=⎩⎪⎪⎪⎨⎪⎪⎪⎧n1n+10n≡0(mod4)n≡1(mod4)n≡2(mod4)n≡3(mod4)
那么代码就很容易写出来。
不打表的话可以推出这样的结论:对于一个奇数
n
n
n,
n
⨁
(
n
−
1
)
=
1
n\bigoplus(n-1)=1
n⨁(n−1)=1,这是非常显然的。那么我们统计奇数的个数,如果有奇数个奇数就相当于是奇数个1异或,答案就是1,否则就是0。
如果
n
n
n 是偶数,那么
S
n
=
S
n
+
1
⨁
(
n
+
1
)
S_n=S_{n+1}\bigoplus (n+1)
Sn=Sn+1⨁(n+1),同样可以
O
(
1
)
O(1)
O(1) 求出,变形后结果和打表出来的规律是一样的。
P1297 [国家集训队]单选错位
题目链接
最终求的期望等于每道题做对的概率之和,那么就要求出每道题做对的概率
对于第
i
i
i 道题:
- 若 a i < a i + 1 a_i<a_{i+1} ai<ai+1,有 a i a i + 1 \dfrac{a_i}{a_{i+1}} ai+1ai 的可能使得正确答案在 [ 1 , a i ] [1,a_i] [1,ai] 中,其中又有 1 a i \dfrac{1}{a_{i}} ai1 的概率做对;剩下 a i + 1 − a i a i + 1 \dfrac{a_{i+1}-a_i}{a_{i+1}} ai+1ai+1−ai 的可能是正确答案在 ( a i , a i + 1 ] (a_i,a_{i+1}] (ai,ai+1] 中,做对的概率为 0 0 0。因此在这种情况下做对的概率是 1 a i + 1 \dfrac{1}{a_{i+1}} ai+11
- 若 a i = a i + 1 a_i=a_{i+1} ai=ai+1,显然做对的概率是 1 a i \dfrac{1}{a_{i}} ai1
- 若 a i > a i + 1 a_i>a_{i+1} ai>ai+1,类似第一种情况可以得到概率是 1 a i \dfrac{1}{a_{i}} ai1
综上,做对某个题的概率是 1 max ( a i , a i + 1 ) \dfrac{1}{\max(a_i,a_{i+1})} max(ai,ai+1)1 。
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef vector<int> vi;
typedef vector<ll> vll;
template <typename T>
inline void read(T &x)
{
T data = 0, f = 1;
char ch = getchar();
while (!isdigit(ch))
{
if (ch == '-')
f = -1;
ch = getchar();
}
while (isdigit(ch))
{
data = (data << 3) + (data << 1) + ch - '0';
ch = getchar();
}
x = f * data;
}
const int inf = 0x3f3f3f3f;
const double eps = 1e-8;
const int maxn = 1e7 + 9;
int a[maxn];
signed main()
{
//freopen("in.txt","r",stdin);
//freopen("data.txt","w",stdout);
//std::ios::sync_with_stdio(false);
//std::cin.tie(0);
//std::cout.tie(0);
int n, A, B, C;
scanf("%d%d%d%d%d", &n, &A, &B, &C, a + 1);
for (int i = 2; i <= n; i++)
a[i] = ((long long)a[i - 1] * A + B) % 100000001;
for (int i = 1; i <= n; i++)
a[i] = a[i] % C + 1;
a[n + 1] = a[1];
double ans = 0.0;
for (int i = 1; i <= n; i++)
ans += 1 / (double)max(a[i], a[i + 1]);
printf("%.3f\n", ans);
//fclose(stdin);
//fclose(stdout);
return 0;
}