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;
}
posted @ 2020-12-07 21:55  ullio  阅读(93)  评论(0编辑  收藏  举报