• 【Codeforces 1453D】Checkpoints


    题目链接

    链接

    翻译

    每个阶段都有 (frac{1}{2}) 的几率失败,失败了会回到上一个存档点。

    想让玩家的期望尝试次数为 (k),问你能否设计出一个不超过 (2000) 级台阶的策略,满足这个要求。

    题解

    如果只有一个 (1) 的话,那么期望尝试次数为 (2)。假设后面出现了一个 (0),即 10,那么到达第 (2) 层且通过了第二层(能够到达第三层了)的期望次数

    是多少呢? 第一层通过了,次数是 (2),然后到达第二层,进行一次尝试。也即 (2+1=3)。但是第二层也只有 (frac{1}{2}) 的几率成功。

    所以也应该要乘 (2),即到达第二层且通过第二层的期望次数为 (2*(2+1)=6)。(失败了就要重新从第一层再上)

    不难看出,假设 100000... 的长度为 (i),设 (x_i) 表示 (i) 层都通过的期望次数。则 (x_{i+1}=2*(x_i+1)) 也即 (x_i = 2^{i+1}-2)

    并且,只要再出现一个 (1) 了,就要重新算期望,即 (1) 把不同的段分隔开了。

    然后说下构造策略,首先,(x_i) 总是一个偶数,所以 (k) 为奇数直接 (-1)

    然后,对于所给的偶数期望 (k),我们可以这么玩。会发现 11000.. (注意这里开头有两个连续 (1),长度设为 (i+1)) 对应的需要重新试的次数为 (2^{i+1}),因为加上了第一个 (1) 的两次。

    只不过这里 (i>=1),所以,对于 (kge4) 的时候,我们只要用 (11000..) 这样对应的 (2^{(i+1)}) 去减 (k) 就好。

    因为二进制分解的缘故,我们总能让 (k) 对应的二进制中大于等于 (2^2) 对应的位都变成 (0),因此一直减的结果就是 (k) 最后等于 (2) 或者 (0)

    等于 (2) 的时候再补一个 (1) 就好啦。

    构造出来的层数是 (1+2+3...log_2K) 这个数量,不会超过 (2000)

    代码

    #include <bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    vector<int> ans;
    
    int main(){
        // freopen("C://1.cppSourceProgram//rush.txt","r",stdin);
        ios::sync_with_stdio(0),cin.tie(0);
        int T;
        cin >> T;
    
        while (T--){
            LL k;
            cin >> k;
            //[1] 特殊判断
            if (k % 2 == 1){
                cout << -1 << endl;
                continue;
            }
            //[2] 用1(期望值为2, 10000...0(1000..0长度为 i 期望值为2^(i+1)-2
            //合在一起就是 2^(i+1), 但是这里 i >= 1
            //所以如果k >= 4, 那么就用11000的 batch 减
            ans.clear();
            while (k >= 4){
                ans.push_back(1);
                ans.push_back(1);
                LL cur = 4;
                int i = 1;
                while (cur*2 <= k){
                    cur*=2;
                    i++;
                }
                for (int j = 1;j <= i-1; j++){
                    ans.push_back(0);
                }
                k -= cur;
            }
            //k=2或k=0
            if (k == 2){
                ans.push_back(1);
            }
            cout << (int)ans.size() << endl;
            int len = ans.size();
            for (int i = 0;i < len; i++){
                cout << ans[i];
                if (i == len-1){
                    cout << endl;
                }else{
                    cout << " ";
                }
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    [转]在C#中使用异步Socket编程实现TCP网络服务的C/S的通讯构架(一)
    Ubuntu操作系统安装使用教程 转载
    ArcInfo和MapInfo的比较 转 http://www.cnblogs.com/njnudt/archive/2007/07/18/821974.html
    jxl导出excel
    flex 图表
    telnet/ssh基本知识
    flex 判断数据类型的几种方法
    友人记
    16进制颜色表
    Ajax不能提交excel
  • 原文地址:https://www.cnblogs.com/AWCXV/p/14148214.html
Copyright © 2020-2023  润新知