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;
}
原文地址:https://www.cnblogs.com/ullio/p/14099942.html