zoukankan      html  css  js  c++  java
  • Solution -「JOISC 2021」古老的机器

    (mathcal{Description})

      Link.

      这是一道通信题。

      对于长度为一个 (n),仅包含字符 X, Y, Z 的字符串 (s),将其中 (n) 个字符按任意顺序删去,定义删除方案的权值为在子串 XYZ 中删除 Y 的次数。实现两个函数:

    • void Anna(int N, std::vector<char> S),获取字符串信息,传递不超过 (7 imes10^4)01 位用于通信;
    • void Bruno(int N, int L, std::vector<int> A),获取通信信息,给出权值最大的删除方案。

      (nle10^5)

    (mathcal{Solution})

      先看看怎么求最大权值。考虑当前最左侧 X 的位置 (i) 与最左侧 Z 的位置 (j),若 (j<i),显然删掉 (j) 无任何影响;否则考虑 (i<k<j)(s_k) 必然取 XY。那么从 (j-1) 逆序删除到 (i+1),最后删除掉 (j),继续迭代。容易(真的容易)看出这就是最大化权值的方案。

      那么 Anna 需要告诉 Bruno 哪些信息呢?——唯一的一个 (i),和若干 (j)。一个小小的压缩方式是,对于连续的 Z,仅保留最右端的。特别地,在标记 X(1) 的后面强制补一个 (0) 站位,我们就把信息串转化为长度为 (n+1),不存在连续 (1) 的数字串。每 (W) 为一段,利用 Fibonacci 数列求出每段的字典序编号,再转化为二进制输出,就能传递信息啦。

      观察标称可知,(W=63),此时一段的总情况数接近 (2^{44}),损失较小。运算过程当然是 (mathcal O(n)) 的,信息长度也就比 (7 imes10^4) 少一百来次。

    (mathcal{Code})

    • Anna.cpp
    /* Clearink */
    
    #include "Anna.h"
    #include <vector>
    
    #ifndef MY_REP_DEFINED
    #define MY_REP_DEFINED
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    #endif
    
    namespace {
    
    typedef unsigned long long ULL;
    
    const int MAXN = 1e5, W = 63, B = 44;
    int n;
    std::vector<char> s;
    bool key[MAXN + W + 5];
    ULL fib[W + 5];
    
    inline void mark() {
        int i = 0;
        while ( i < n && s[i] != 'X' ) ++i;
        key[i] = true;
        for ( int j = i + 1; j < n; ++j ) {
            while ( j < n && s[j] != 'Z' ) ++j;
            while ( j + 1 < n && s[j + 1] == 'Z' ) ++j;
            if ( i >= n || j >= n ) break;
            key[j + 1] = true;
        }
    }
    
    inline void encode() {
        fib[0] = 1, fib[1] = 2;
        rep ( i, 2, W ) fib[i] = fib[i - 1] + fib[i - 2];
        
        for ( int l = 0; l <= n; l += W ) {
            ULL msg = 0;
            rep ( i, l, l + W - 1 ) if ( key[i] ) {
                msg += fib[repi - i];
            }
            rep ( i, 0, B - 1 ) Send( msg >> i & 1 );
        }
    }
    
    } // namespace.
    
    void Anna( int n, std::vector<char> s ) {
        ::n = n, ::s = s;
        mark(), encode();
    }
    
    
    • Bruno.cpp
    /* Clearink */
    
    #include "Bruno.h"
    #include <vector>
    
    #ifndef MY_REP_DEFINED
    #define MY_REP_DEFINED
    #define rep( i, l, r ) for ( int i = l, rep##i = r; i <= rep##i; ++i )
    #define per( i, r, l ) for ( int i = r, per##i = l; i >= per##i; --i )
    #endif
    
    namespace {
    
    typedef long long ULL;
    
    const int MAXN = 1e5, W = 63, B = 44;
    ULL fib[W + 5];
    int n;
    std::vector<int> msg;
    bool key[MAXN + W + 5];
    
    inline void decode() {
        fib[0] = 1, fib[1] = 2;
        rep ( i, 2, W ) fib[i] = fib[i - 1] + fib[i - 2];
    
        for ( int l = 0; l < msg.size(); l += B ) {
            ULL val = 0;
            per ( i, l + B - 1, l ) val = val << 1 | msg[i];
            rep ( i, l / B * W, i + W - 1 ) {
                if ( val >= fib[repi - i] ) {
                    key[i] = true, val -= fib[repi - i];
                }
            }
        }
    }
    
    inline void solve() {
        int i = 0;
        while ( i < n && !key[i] ) Remove( i++ );
        if ( i == n ) return ;
        for ( int j = i + 1, las = i; j < n; ) {
            while ( j < n && !key[j + 1] ) ++j;
            per ( k, j - 1, las + 1 ) Remove( k );
            if ( j < n ) Remove( las = j++ );
        }
        Remove( i );
    }
    
    } // namespace.
    
    void Bruno( int n, int l, std::vector<int> msg ) {
        ::n = n, ::msg = msg;
        decode(), solve();
    }
    
    
  • 相关阅读:
    功能点方法
    学数答题160908-数论不等式
    学数答题160903-函数方程
    学数答题160906-不等式最值
    学数答题160905-函数方程
    学数答题160904-不等式
    学数答题160903-三角函数
    kitti-b站教程
    kitti数据集介绍
    SLAM:理论与实践
  • 原文地址:https://www.cnblogs.com/rainybunny/p/14924092.html
Copyright © 2011-2022 走看看