概述
CF #688D
原题链接
题意:构造一串长为n的01序列 ( n ≤ 2000 ) (nleq 2000) (n≤2000),有 1 2 frac12 21的概率成功通过第i个关卡,如果失败,立即返回到小于等于i的最大的1位置。
为何单独一个1,通过的期望次数是2呢?
我们假设穿过一个单独的1的期望是x
有
1
2
frac12
21的概率一次通过,也有
1
2
frac12
21的概率失败,那么还需要x的期望通过。
于是
x
=
1
2
∗
1
+
1
2
∗
(
x
+
1
)
x=frac12*1+frac12*(x+1)
x=21∗1+21∗(x+1),可以求得x = 2。
我们最后构造的序列可以分解成若干 1000 … 1000dots 1000…序列的形式
我们定义 f [ i ] f[i] f[i]为开头一个1,后面跟i - 1个0的期望步数。
那么由上面的推导得 f [ 1 ] = 2 f[1] = 2 f[1]=2
可得下面的式子:
f
[
i
]
=
f
[
i
−
1
]
+
1
+
1
2
∗
{
f
[
i
−
1
]
+
(
f
[
i
]
−
f
[
i
−
1
]
)
}
f[i]=f[i-1]+1+frac12*{f[i-1]+(f[i]-f[i-1])}
f[i]=f[i−1]+1+21∗{f[i−1]+(f[i]−f[i−1])}
为什么是这个方程呢?
想通过第i个关卡,前提是突破前i - 1个关卡,期望是
f
[
i
−
1
]
f[i-1]
f[i−1]
现在我们用一步尝试通过第i个关卡,期望是1
1
2
frac12
21的概率突破了第i个关卡,这样就不需要多余的步数。
如果突破失败,就要回到上一个1的位置,回到第i - 1的位置需要步数
f
[
i
−
1
]
f[i-1]
f[i−1],突破第i个关卡需要期望
f
[
i
]
−
f
[
i
−
1
]
f[i]-f[i-1]
f[i]−f[i−1]
移项就能得到,
f
[
i
]
=
2
∗
f
[
i
−
1
]
+
2
f[i]=2*f[i-1]+2
f[i]=2∗f[i−1]+2
我们可以发现只有期望为偶数时,才能构造,奇数无解。
偶数直接从大到小构造1000
…
dots
…串即可。
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int inf = 0x3f3f3f3f;
const int MAXN = 1e6 + 10;
const int mod = 1e9 + 7;
vector<int> ans;
ll pre[100];
int main()
{
int t;
scanf("%d", &t);
for (int i = 1; i <= 60; i++) {
pre[i] = pre[i - 1] * 2 + 2;
}
while (t--) {
ans.clear();
ll k;
scanf("%lld", &k);
bool flag = false;
while (k) {
for (int i = 60; i >= 1; i--) {
if (pre[i] <= k) {
k -= pre[i];
ans.emplace_back(1);
for (int j = 1; j < i; j++) {
ans.emplace_back(0);
}
break;
}
}
if (k & 1) {
flag = true;
break;
}
}
if (flag || ans.size() > 2000) {
printf("-1n");
continue;
}
cout << ans.size() << endl;
for (int i = 0; i < ans.size(); i++) {
if (i) printf(" ");
printf("%d", ans[i]);
}
printf("n");
}
return 0;
}
最后
以上就是繁荣斑马为你收集整理的CF#688 D. CheckpointsCF #688D的全部内容,希望文章能够帮你解决CF#688 D. CheckpointsCF #688D所遇到的程序开发问题。
如果觉得靠谱客网站的内容还不错,欢迎将靠谱客网站推荐给程序员好友。
发表评论 取消回复