arrows blog

解いた問題などを適当に書いていきます。

AOJ 0270 - Modular Query

問題概要

N個の数字(c1,c2,...,cN)が与えられる。Q個のクエリがあり、各クエリでqが与えられる。このときN個の数字の中でqで割った余りの最大値を出力せよ。

制約

  • 2 ≤ N ≤ 300000
  • 2 ≤ Q ≤ 100000
  • 1 ≤ ci ≤ 300000
  • 1 ≤ qi ≤ 300000

解法

まず、入力されたN個の数字をciの最大の要素数である300000(+1)の配列に埋め込む(この配列は0で初期化)。
例えば、入力例だと、(0-indexedで) 0 0 0 3 0 0 0 0 8 9 0 0 0 ....
のようになる。

次に i > 0 のときに c[i] = max(c[i],c[i-1]) をする。
これは次の埋め込んだ要素が来るまで同じ数字を並べている。
例えば、入力例だと、(0-indexedで) 0 0 0 3 3 3 3 3 8 9 9 9 9 ....
のようになる。

ここである数 x (x>0)を考えると、 x で割った余りが最大になる場合は、
((x-1) + x*k) % x (k = 0,1,2,3,....) の場合であるから、
c[i]についてこの操作を行えば最大の余りを求めることができる。

コード

#include <bits/stdc++.h>
 
using namespace std;
 
#define M 600001
 
int main(){
  int N,Q,q,in,c[M]={0};
  cin >> N >> Q;
  for(int i = 0 ; i < N ; i++){
    scanf("%d",&in);
    c[in] = in;
  }
  for(int i = 1 ; i < M ; i++){
    c[i] = max(c[i],c[i-1]);
  }
  while(Q--){
    cin >> q;
    int r = 0;
    for(int i = q-1 ; i < M ; i += q){
      r = max(r,c[i]%q);
    }
    printf("%d\n",r);
  }
  return 0;
}