• 牛客练习赛1 C


    链接:https://www.nowcoder.com/acm/contest/2/C
    来源:牛客网

    题目描述

    shy有一个队列a[1], a[2],…,a[n]。现在我们不停地把头上的元素放到尾巴上。在这过程中我们会得到n个不同的队列,每个队列都是a[k],a[k+1],…,a[n],a[1],…,a[k-1]的形式。在这些队列中,我们可以找到字典序最小的。
    shy无聊的时候会给队列的每个元素加一玩。但是为了使得游戏不这么无聊,shy加一以后会给每个元素模m,这样子字典序最小的序列就会变了,生活就变得有趣。
    很显然这样子加m次以后,序列会变成原来的样子。所以现在shy想知道,在他没有加一前,加一时,加二时,….,加m-1时字典序最小的序列的第k(和上面的k没有关系)个元素分别是几。

    输入描述:

    第一行三个整数n,m,k表示序列长度,取模的数和要求的序列的第几个元素。
    接下来一行n个整数表示初始序列。

    输出描述:

    m个整数表示答案。
    示例1

    输入

    5 6 3
    1 2 1 2 3

    输出

    1
    2
    3
    5
    5
    0

    备注:

    对于30%的数据,1≤n,m≤100;
    对于100%的数据,1≤n,m≤50000, 1≤k≤n, 0≤a[i]<m;

    题解

    字符串$hash$。

    每个数字都会变且仅变一次零。

    如果上一次到这一次没有零产生,那么答案的位置不会改变。

    否则重新寻找答案产生的位置。

    两个字符串比较字典序,字符串$hash$一下,找$lcp$即可。

    #include<bits/stdc++.h>
    using namespace std;
    
    long long mod[2];
    long long base[2];
    const int maxn = 1e5 + 10;
    int a[maxn], n, m, k;
    long long h[2][maxn];
    long long b[2][maxn];
    int ans[maxn];
    vector<int> g[maxn];
    
    void init() {
      mod[0] = 1e9 + 7;
      mod[1] = 1e9 + 7;
      base[0] = 131LL;
      base[1] = 313LL;
      b[0][0] = b[1][0] = 1LL;
      for(int i = 1; i < maxn; i ++) {
        for(int t = 0; t < 2; t ++) {
          b[t][i] = b[t][i - 1] * base[t] % mod[t];
        }
      }
    }
    
    int check(int x, int y, int len) {
      if(len == 0) return 1;
      if(x > y) swap(x, y);
      for(int t = 0; t < 2; t ++) {
        long long AA = 0, BB = 0;
        if(x > 0) AA = h[t][x - 1] * b[t][len] % mod[t];
        if(y > 0) BB = h[t][y - 1] * b[t][len] % mod[t];
        long long A = (h[t][x + len - 1] - AA + mod[t]) % mod[t];
        long long B = (h[t][y + len - 1] - BB + mod[t]) % mod[t];
        if(A != B) return 0;
      }
      return 1;
    }
    
    int ok(int x, int y, int f) {
      int L = 0, R = n, pos = -1;
      while(L <= R) {
        int mid = (L + R) / 2;
        if(check(x, y, mid)) pos = mid, L = mid + 1;
        else R = mid - 1;
      }
      if(pos == n) return 0;
      if((a[x + pos] + f) % m
       < (a[y + pos] + f) % m) return 1;
      return 0;
    }
    
    int main() {
      init();
      scanf("%d%d%d", &n, &m, &k);
      k --;
      long long A[2];
      A[0] = A[1] = 0;
      for(int i = 0; i < n; i ++) {
        scanf("%d", &a[i]);
        a[i + n] = a[i];
        g[(m - a[i]) % m].push_back(i);
      }
      for(int i = 0; i < 2 * n; i ++) {
        for(int t = 0; t < 2; t ++) {
          A[t] = A[t] * base[t] % mod[t];
          A[t] = (A[t] + a[i]) % mod[t];
          h[t][i] = A[t];
        }
      }
      
      int p = 0;
      for(int i = 1; i < n; i ++) {
        if(ok(i, p, 0)) p = i;
      }
      ans[0] = a[p + k];
      for(int i = 1; i < m; i ++) {
        if(g[i].size() == 0) {
          ans[i] = ans[i - 1] + 1;
        } else {
          p = g[i][0];
          for(int j = 1; j < g[i].size(); j ++) {
            if(ok(g[i][j], p, i)) p = g[i][j];
          }
          ans[i] = (a[p + k] + i) % m;
        }
      }
      for(int i = 0; i < m; i ++) {
        printf("%d
    ", ans[i]);
      }
      return 0;
    }
    
  • 相关阅读:
    bzoj1467 Pku3243 clever Y
    bzoj2242 [SDOI2011]计算器
    卡特兰数
    洛谷P1290 欧几里得的游戏
    bzoj2277 [Poi2011]Strongbox
    poj2406 Power Strings
    Codeforces 892 D.Gluttony
    Codeforces 892 C.Pride
    Codeforces 892 B.Wrath
    Codeforces 892 A.Greed
  • 原文地址:https://www.cnblogs.com/zufezzt/p/8360598.html
Copyright © 2020-2023  润新知