• Google Code Jam 2019 Qualification 题解


    A. Foregone Solution

    题意:给你一个大于1小于1e100的整数(至少有一个数位的值是4),让你把它表示为两个正整数的和,并且这两个正整数的十进制表达中都不能包含数位4。保证有解

    思路:每个数位可以独立的解决。

    实现:设最后答案的两个数是a和b,然后把不是4的数位都分给a,把是4的数位拆成(1,3)或(2, 2) 分给a和b。因为题目保证至少存在一个数位位4,所以这样分a和b一定都是正整数。

    官方题解:可以随机化!随机选择a,然后检查a和n-a是否合法

    B. You Can Go Your Own Way

    题意:在一个n*n的网格上,从左上角出发,只能向右或者向下走,经过2*n-2步到达右下角。题目给出了一个由Left(E,as in East)和Down(S,as in South)组成的路径prod,要求你给出一个路径dev,使得不存在在某一个点,dev和prod走了相同的方向。(即如果dev和prod同时经过了某个点,且dev走的下一步是E,那么prod必须走S,以此类推)

    思路:关于对角线反置一下prod就好了

    实现:读入prod,将E和S互换。

    证明:通过上述构建方式得到dev,如果dev不合法,without the loss of generality,设第一次路径重合的地方是(a,b)-> (a,b+1)。由于这条边在dev中也存在,那么(b,a)-> (b+1, a)这条边在prod中也存在。我们不妨假设prod中,先走了(a,b)-> (a,b+1),后走了(b,a)-> (b+1, a),那么易知 (b,a)这个点是(a,b)之后经过的。所以有

    b > a 且 a > b。矛盾

    C. Cryptopangrams

    题意:出题人随机选了26个不超过1e100的素数,按照从小到大排列,把每个素数分给起对应的字母,得到了一个由大写字母到这26个素数的一个bijection。然后出题人通过这个bijection对一段message加密,加密过程为

    (1)把每个字符替换成其对应的素数,得到一个长度和message相同的整数数列,计为v[]

    (2)生成一个长度为n-1的数字序列a[],其中a[i] = v[i] * v[i+1]

    保证26字符每个都至少在message里出现一次。n不超过100,告诉你数列a[],让你求出原文。

    思路:观察到,我们只要找出一个v[i],剩下的v[i]就可以通过某些a[x]和之前得到的v[y]作商得到。下面我们想怎么样可以找出一个v[i]。因为每个字符都出现一次,那么在message中一定存在i使得message[i] != message[i+2](否则,message只会由至多两种字符组成,因为奇数位都相同,偶数位也是),继而得到v[i] != v[i+2] -> v[i] * v[i+1] != v[i+2] * v[i+1],即a[i] != a[i+1]。然后v[i+1] = gcd(a[i], a[i+1])。

    实现:

     1 import java.io.*;
     2 import java.util.*;
     3 import java.text.*;
     4 import java.math.*;
     5 public class Solution
     6 {
     7     public static void main(String args[])
     8     {
     9         Scanner stdin = new Scanner(System.in);        
    10         int T = stdin.nextInt();
    11         for (int kase = 1; kase <= T; ++kase)
    12             {
    13                 System.out.print("Case #" + Integer.toString(kase) + ": ");
    14                 BigInteger N = stdin.nextBigInteger();
    15                 int n = stdin.nextInt();
    16                 BigInteger[] cipher = new BigInteger[n];
    17                 BigInteger[] original = new BigInteger[n+1];
    18                 for (int i = 0; i < n; ++i)
    19                     {
    20                         cipher[i] = stdin.nextBigInteger();
    21                         // System.out.println(cipher[i]);
    22                     }
    23                 int tar = 0;
    24                 for (tar = 0; tar < n-1 && cipher[tar].equals(cipher[tar+1]); ++tar);
    25                 original[tar+1] = cipher[tar].gcd(cipher[tar+1]);
    26                 for (int i = tar; i >= 0; --i) original[i] = cipher[i].divide(original[i+1]);
    27                 for (int i = tar+1; i < n; ++i)
    28                     original[i+1] = cipher[i].divide(original[i]);
    29                 TreeSet<BigInteger> set = new TreeSet<BigInteger>();
    30                 for (int i = 0; i < n+1; ++i)
    31                     set.add(original[i]);                
    32                 TreeMap<BigInteger, Character> mapping = new TreeMap<BigInteger, Character>();
    33                 assert(set.size() == 26);
    34                 char base = 'A';
    35                 for (BigInteger code : set)
    36                     {
    37                         mapping.put(code, base);
    38                         ++base;
    39                     }
    40                 for (int i = 0; i < n+1; ++i)
    41                     System.out.print(mapping.get(original[i]));
    42                 System.out.println();
    43             }
    44     }
    45 };
    View Code

    D. Dat Bae

    题意:交互题。大概就是,有N (<= 1024)个bit,里面有B(<=min(N-1, 15))个bit是disabled的。每次你可以send一个长度为N的01串bits,judge会将bits中disabled的bit删掉,返回给你这个长度为N-B的01串。下面要求你在不超过F(小 case F = 10, 大 case F = 5)次询问中,测出哪些bit是disabled的。

    思路:

    (a) 小 case。比较容易猜出10和1024(2^10)之间的关系,可以二分区间解决(其实有点像自上而下建立线段树)。首先,send一个前N/2个bit都是0,后面 (N+1)/2个bit都是1的询问,得到judge的回复response后,数response中0的个数和1的个数(由于我们的询问,0只能是前导0,1也只能是后缀1),这样我们就知道前N/2个bit和剩下的bit各自有几个bit是坏的,同时我们也知道前N/2个bit在response中对应的有效区间是哪一块了。之后我们前N/2个bit和后面(N+1)/2个bit就不相关了,我们可以按照相似的步骤递归处理前半段和后半段,如果发现一整段都是坏的,我们就可以停止递归。这样最差情况在10步内就可以求出所有的disabled bit。

    (b) 大 case。其实小case做法的本质就是确定某个区间在response中对应的区间是什么。我们发现,B不会超过15,那么我们可以把N分成每MAGIC=16个一组,一共大约N/MAGIC组。在第一询问的时候,第0组全填0,第1组全填1,以此类推,偶数组填0,奇数组填1。这样会发现,在response中,一定有交替出现的N/MAGIC组连续的0和1,即我们可以直接确定每个组在response对应的区间。(其实MAGIC=15也可以,容易想但不太好解释。)之后我们就可以确定若干个(其实是不超过15个,但是这个数字对复杂度没有影响)长度为MAGIC的包含disable bit的区间。之后我们就按照小case中的做法处理这些区间,需要的询问数为log2(MAGIC) <= 4,加上我们第一次的询问,一共不超过5次。

    实现:

      1 #include <iostream>
      2 #include <cstdio>
      3 #include <cstdlib>
      4 #include <iomanip>
      5 
      6 #include <vector>
      7 #include <cstring>
      8 #include <string>
      9 #include <queue>
     10 #include <deque>
     11 #include <stack>
     12 #include <map>
     13 #include <set>
     14 
     15 #include <utility>
     16 #include <list>
     17 
     18 #include <cmath>
     19 #include <algorithm>
     20 #include <cassert>
     21 #include <bitset>
     22 #include <complex>
     23 #include <climits>
     24 #include <functional>
     25 #include <unordered_set>
     26 #include <unordered_map>
     27 using namespace std;
     28 
     29 typedef long long ll;
     30 typedef pair<int, int> ii;
     31 typedef pair<ll, ll> l4;
     32 typedef pair<double, double> dd;
     33 #define mp make_pair
     34 #define pb push_back
     35 
     36 #define debug(x) cerr << #x << " = " << x << " "
     37 
     38 
     39 vector<int> ans;
     40 string rpc(const string &s)
     41 {
     42     cout << s << endl;
     43     fflush(stdout);
     44     string ret;
     45     cin >> ret;
     46     return ret;
     47 }
     48 const int MAGIC = 15;
     49 typedef pair<ii, ii> i4;
     50 string initial_query(int n)
     51 {
     52     string ret = "";
     53     for (int i = 0; i < n; ++i)
     54     {
     55         ret += '0' + (i/MAGIC%2);
     56     }
     57     return ret;
     58 }
     59 void deal(vector<i4> &to_push, int start, int expect_count, int start_ptr, int actual_count)
     60 {
     61     if (actual_count == expect_count) return;
     62     if (actual_count == 0)
     63     {
     64         for (int j = 0; j < expect_count; ++j) ans.pb(start+j);
     65         return;
     66     }
     67     to_push.pb(mp(mp(start,expect_count),mp(start_ptr,actual_count)));
     68 }
     69 vector<i4> initial_rpc(int n)
     70 {
     71     string response = rpc(initial_query(n));
     72     vector<i4> ret;
     73 
     74     for (int i = 0, ptr = 0; i * MAGIC < n; ++i)
     75     {
     76         const int expected = i&1;
     77         const int expected_count = min(MAGIC, n - i * MAGIC);
     78         int start_ptr = ptr;
     79         while (ptr < response.size()
     80                && ptr-start_ptr+1 <= expected_count
     81                && response[ptr] == '0'+expected)
     82             ++ptr;
     83         deal(ret, i*MAGIC, expected_count, start_ptr, ptr-start_ptr);
     84         /*
     85         if (ptr - start_ptr == expected_count) continue;
     86         if (ptr == start_ptr)
     87         {
     88             for (int j = 0; j < expected_count; ++j) ans.pb(i*MAGIC+j);
     89             continue;
     90         }
     91         ret.pb(mp(mp(i*MAGIC, expected_count), mp(start_ptr, ptr-start_ptr)));
     92          */
     93     }
     94     return ret;
     95 }
     96 vector<i4> solve(int n, const vector<i4> &v)
     97 {
     98     string query = string(n, '1');
     99     for (auto e : v)
    100     {
    101         for (int i = 0; i < e.first.second/2; ++i)
    102             query[e.first.first+i] = '0';
    103     }
    104     string response = rpc(query);
    105     vector<i4> ret;
    106     for (auto e : v)
    107     {
    108         int len = e.first.second/2;
    109         int last_zero = -1;
    110         for (int i = 0; i < e.second.second; ++i)
    111             if (response[e.second.first+i] == '0') last_zero = i;
    112         //for (int i = 0; i <= last_zero; ++i) assert(response[e.second.first+i] == '0');
    113         //for (int i = last_zero+1; i < e.second.second; ++i) assert(response[e.second.first+i] == '1');
    114         deal(ret, e.first.first, len, e.second.first, last_zero+1);
    115         deal(ret, e.first.first+len, e.first.second-len, e.second.first+last_zero+1, e.second.second-last_zero-1);
    116     }
    117     return ret;
    118 }
    119 int main()
    120 {
    121     ios::sync_with_stdio(false);
    122     cin.tie(0);
    123     int T; cin >> T;
    124     for (int kase = 1; kase <= T; ++kase)
    125     {
    126         int n, b, f;
    127         cin >> n >> b >> f;
    128         ans.clear();
    129         auto v = initial_rpc(n);
    130         while (f > 0 && !v.empty()) --f, v = solve(n, v);
    131         assert(v.empty());
    132         assert(ans.size() == b);
    133         sort(ans.begin(), ans.end());
    134         for (int i = 0; i < ans.size(); ++i)
    135             cout << ans[i] << " ";
    136         string return_code = rpc("");
    137 
    138     }
    139 }
    140 /*
    141  1
    142  10 5 5
    143  101010101000010100101
    144  0 2 4 6 8 13 15  18 20
    145  */
    View Code
  • 相关阅读:
    Toad 常用快捷键
    Oracle Form删除list项
    不得重新使用的登录口令
    OE_ORDER_PUB.PROCESS_ORDER to Release a hold on sales order in R12
    OE_ORDER_PUB.PROCESS_ORDER to Apply hold on a sales order
    说明性弹性域段
    使用VPD解决EBS中信息屏蔽问题
    Oracle EBS客户化程序中格式化金额
    Form开发中组件控制的几个常用方法
    .Net的差评
  • 原文地址:https://www.cnblogs.com/skyette/p/10665061.html
Copyright © 2020-2023  润新知