zoukankan      html  css  js  c++  java
  • Codeforces Round #429 (Div. 2)

    题目链接:https://codeforces.com/contest/841

    A - Generous Kefa

    签到题,用一下鸽巢原理。

    B - Godsend

    题意:有一个n个元素的正整数序列,两个玩家轮流操作,玩家A先操作。玩家A每次可以选连续的一段元素,满足:他们的和为奇数,然后删除选择的元素,玩家B每次可以选连续的一段元素,满足:他们的和为偶数,然后删除选择的元素。每次删除完元素过后,剩余的部分会重新连接在一起。谁无法操作谁就输。问最优策略下谁会赢。

    题解:显然假如全部元素的和为奇数,就是A赢。否则假如全部元素都是偶数,那么就是B赢。会不会有B赢的其他情况呢?既然是B赢,那么必然是B操作最后一步,也就是最后一步必定全部元素的和为偶数,由于是A先操作,假如一开始全部元素的和为偶数,且至少有一个奇数,已知就是至少有两个奇数,那么A肯定取走奇数的一部分,剩下的一部分和也是奇数,也就是只有当A起手不能操作的时候B才能赢。然后马上就能发现必胜策略:把最后一个奇数左边的一段在第一步都拿走。

    C - Leha and Function

    题意:定义一个函数 (F(n,k)) 表示在 ([1,n]) 中选 (k) 个元素形成的子集,然后取每个子集的最小值的数学期望。给两个长度都是 (m) 的正整数数组 (A)(B) ,满足 (min(A)geq max(B)) ,重新排列 (A) ,使得 (sumlimits_{i=1}^{m}F(A'_i,B_i)) 最大,这里的 (A') 表示重新排列之后的数组 (A)

    题解:看了一下样例貌似是大的配小的这样排序,但是不知道会不会有坑。用微扰法观察:设 (A_1leq A_2)(B_1leq B_2) ,则 (F(A_1,B_1)+F(A_2,B_2)leq F(A_1,B_2)+F(A_2,B_1)) 是否成立?先考虑 (F(n,k)) 本身有什么性质,首先当 (k) 不变且 (n) 变大,答案显然变大;当 (n) 不变 且 (k) 变大,就感觉不是特别明显。考虑

    (F(6,1)=frac{1}{6}(1+2+3+4+5+6)=frac{7}{2})
    (F(6,2)=frac{1}{15}(1*5+2*4+3*3+4*2+5*1+6*0)=frac{1}{15}(5+8+9+8+5+0)=frac{7}{3})
    (F(6,3)=frac{1}{C_6^3}(1*C_5^2+2*C_4^2+3*C_3^2+4*C_2^2+5*C_1^2+6*C_0^2)=frac{7}{4})
    (F(6,4)=frac{1}{C_6^4}(1*C_5^3+2*C_4^3+3*C_3^3+4*C_2^3+5*C_1^3+6*C_0^3)=frac{7}{5})
    (F(6,5)=frac{1}{C_6^5}(1*C_5^4+2*C_4^4+3*C_3^4+4*C_2^4+5*C_1^4+6*C_0^4)=frac{7}{6})
    (F(6,6)=frac{1}{C_6^6}(1*C_5^5+2*C_4^5+3*C_3^5+4*C_2^5+5*C_1^5+6*C_0^5)=frac{7}{7})

    貌似 (F(n,k)=frac{n+1}{k+1}) ,假如这个式子成立,就能够说明 (F(A_1-1,B_1-1)+F(A_2-1,B_2-1)=frac{A_1B_2+A_2B_1}{B_1B_2}leq F(A_1-1,B_2-1)+F(A_2-1,B_1-1)=frac{A_1B_1+A_2B_2}{B_1B_2}) 。所以贪心的策略确实就是上述的大数配小数。不过这个期望是怎么准确计算呢?从这个求和式貌似看不出什么结果,官方题解貌似是另一种算法。

    struct Node {
        int id, val;
    } A[200005], B[200005];
    
    bool cmp(const Node &n1, const Node &n2) {
        return n1.val < n2.val;
    }
    
    bool cmp2(const Node &n1, const Node &n2) {
        return n1.id < n2.id;
    }
    
    void test_case() {
        int n;
        scanf("%d", &n);
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &A[i].val);
            A[i].id = i;
        }
        for(int i = 1; i <= n; ++i) {
            scanf("%d", &B[i].val);
            B[i].id = i;
        }
        sort(A + 1, A + 1 + n, cmp);
        sort(B + 1, B + 1 + n, cmp);
        for(int i = 1; i <= n; ++i)
            A[i].id = B[n + 1 - i].id;
        sort(A + 1, A + 1 + n, cmp2);
        for(int i = 1; i <= n; ++i)
            printf("%d%c", A[i].val, " 
    "[i == n]);
    }
    

    奇怪的知识增加了:由上面的算法可知: (F(n,k)=frac{sumlimits_{i=1}^{n}i*C_{n-i}^{k-1}}{C_n^k}=frac{n+1}{k+1})

    即:
    (sumlimits_{i=1}^{n}i*C_{n-i}^{k-1}=frac{n+1}{k+1}C_n^k)
    (sumlimits_{i=1}^{n}i*C_{n-i}^{k-1}=C_{n+1}^{k+1})
    (sumlimits_{i=1}^{n}C_i^1*C_{n-i}^{k-1}=C_{n+1}^{k+1})

    但这是为什么呢?有一种非常扭曲的理解:左边是先确定选出的第2个元素的位置,然后在左边选1个元素作为第1个元素,在右边选k-1个元素,方法之间是独立的,可以求和。

  • 相关阅读:
    Javascript异步编程之回调函数
    重绘(redraw或repaint)和 重排(reflow)
    前端性能优化之重排和重绘
    关于options请求的一点理解
    跨域中option请求详解
    手写call、apply、bind函数
    CSS3疑难问题---7、实现元素水平垂直居中
    CSS3疑难问题---8、纯css实现三角形
    【转】Activity启动模式 及 Intent Flags 与 栈 的关联分析
    ListView为什么用setOnItemClick这个方法和onTouch这个方法有冲突
  • 原文地址:https://www.cnblogs.com/KisekiPurin2019/p/12327248.html
Copyright © 2011-2022 走看看