Codeforces Round #688 (Div. 2) D
Codeforces Round #688 (Div. 2) D
大意
略...
思路
我期望不熟.jpg
考虑走到 \(1\) ,期望代价是 \(2\) 步。
设 \(x\) 为走过一个 \(1\) 的期望代价,有 \(x=1+\dfrac{1}{2}*x+\dfrac{1}{2}*0\)
因为花费一个代价,有 \(\dfrac{1}{2}\) 概率成功, \(\dfrac{1}{2}\) 概率在期望走 \(x\) 步之后成功。
当我们走到一个 \(1\) 之后,前面的就完全可以无视,因为即使失败也不可能会到前面。
所以我们仅考虑一个 \(1\) 和一串连续的 \(0\) 组成的串的代价。
不妨设 \(f_i\) 为经过 \(i\) 个 \(0\) 且正准备前往第 \(i+1\) 个 \(0\) 的期望代价。
显然 \(f_0=2\) 因为经过一个 \(1\) 的期望代价是 \(2\)
能够得到递推方程 \(f_{i+1} = f_i+1+\dfrac{1}{2}*0+\dfrac{1}{2}*f_{i+1}\)
整理,易得 \(f_i=2^{i+2}-2\)
所以我们贪心从大往小选择。
代码
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath>
#include <cstring>
using namespace std;
#define ll long long
#define ull unsigned long long
#define cint const int&
#define Pi acos(-1)
const int mod = 998244353;
const int inf_int = 0x7fffffff;
const ll inf_ll = 0x7fffffffffffffff;
const double ept = 1e-9;
int t;
ll k;
ll to[100];
int q[1001], cnt;
int main() {
to[0] = 2;
for(int i=1; i<=61; i++) to[i] = ((to[i-1]+2ll)*2)-2ll;
cin >> t;
while(t--) {
int ans=0;
cnt = 0;
cin >> k;
if(k&1) {cout << -1 << endl; continue;}
for(int i=61; i>=0; i--)
while(k >= to[i]) {
k -= to[i];
q[++cnt] = i;
ans += i+1;
}
cout << ans << endl;
while(cnt) {
int r = q[cnt--];
cout << 1 << ' ';
while(r) {cout << 0 << ' '; --r;}
}
cout << endl;
}
return 0;
}