提供一种直接基于期望推表达式的做法。
设 $p$ 表示走一步成功的概率,$E[x]$ 表示从一个存档点开始,还剩 $x$ 步的距离到达下一个存档点,所需的期望步数。若一次成功,共走 $x$ 步,概率为 $p^x$;若走到第 $i$ 步时失败,概率为 $p^{i-1}(1-p)$,之后需要重新开始,共走 $E[x]$ 步。因此有表达式:
直接将 $p = \frac{1}{2}$ 带入可知:
因此直接构造 $\texttt{100…}$ 的形式,类似二进制拆分进行构造即可。由于 $E[x]$ 为偶数,所以奇数的情况显然无解。
代码如下:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53
| #include <bits/stdc++.h> #define pii pair <int,int> #define init(x) memset (x,0,sizeof (x)) #define ll long long #define ull unsigned long long #define INF 0x3f3f3f3f using namespace std; const int MAX = 1e5 + 5; const int MOD = 1e9 + 7; inline ll read (); void solve () { ll x = read (); if (x & 1) {puts ("-1");return;} vector <ll> f (61,0); for (int i = 0;i <= 60;++i) f[i] = (1ll << (i + 2)) - 2; vector <int> ans; for (int i = 60;~i;--i) { while (x >= f[i]) { x -= f[i]; ans.push_back (1); for (int j = 1;j <= i;++j) ans.push_back (0); } } assert ((int)ans.size () <= 5000); printf ("%d\n",(int) ans.size ()); for (auto v : ans) printf ("%d ",v); puts (""); } int main () { int t = read (); while (t--) solve (); return 0; } inline ll read () { ll s = 0;int f = 1; char ch = getchar (); while ((ch < '0' || ch > '9') && ch != EOF) { if (ch == '-') f = -1; ch = getchar (); } while (ch >= '0' && ch <= '9') { s = s * 10 + ch - '0'; ch = getchar (); } return s * f; }
|