結果
| 問題 |
No.1067 #いろいろな色 / Red and Blue and more various colors (Middle)
|
| コンテスト | |
| ユーザー |
|
| 提出日時 | 2020-06-04 08:11:13 |
| 言語 | C++17 (gcc 13.3.0 + boost 1.87.0) |
| 結果 |
TLE
|
| 実行時間 | - |
| コード長 | 8,889 bytes |
| コンパイル時間 | 3,153 ms |
| コンパイル使用メモリ | 214,904 KB |
| 最終ジャッジ日時 | 2025-01-10 21:06:36 |
|
ジャッジサーバーID (参考情報) |
judge5 / judge3 |
(要ログイン)
| ファイルパターン | 結果 |
|---|---|
| sample | AC * 1 |
| other | AC * 13 TLE * 12 |
ソースコード
#include <bits/stdc++.h>
#ifdef DEBUG
#include <Mylib/Debug/debug.cpp>
#else
#define dump(...)
#endif
/**
* @docs input_vector.md
*/
template <typename T>
std::vector<T> input_vector(int N){
std::vector<T> ret(N);
for(int i = 0; i < N; ++i) std::cin >> ret[i];
return ret;
}
template <typename T>
std::vector<std::vector<T>> input_vector(int N, int M){
std::vector<std::vector<T>> ret(N);
for(int i = 0; i < N; ++i) ret[i] = input_vector<T>(M);
return ret;
}
/**
* @docs input_tuple_vector.md
*/
template <typename T, size_t ... I>
void input_tuple_vector_init(T &val, int N, std::index_sequence<I...>){
(void)std::initializer_list<int>{
(void(std::get<I>(val).resize(N)), 0)...
};
}
template <typename T, size_t ... I>
void input_tuple_vector_helper(T &val, int i, std::index_sequence<I...>){
(void)std::initializer_list<int>{
(void(std::cin >> std::get<I>(val)[i]), 0)...
};
}
template <typename ... Args>
auto input_tuple_vector(int N){
std::tuple<std::vector<Args>...> ret;
input_tuple_vector_init(ret, N, std::make_index_sequence<sizeof...(Args)>());
for(int i = 0; i < N; ++i){
input_tuple_vector_helper(ret, i, std::make_index_sequence<sizeof...(Args)>());
}
return ret;
}
/**
* @docs input_tuples.md
*/
template <typename ... Args>
class InputTuples{
template <typename T, size_t ... I>
static void input_tuple_helper(T &val, std::index_sequence<I...>){
(void)std::initializer_list<int>{(void(std::cin >> std::get<I>(val)), 0)...};
}
struct iter{
using value_type = std::tuple<Args ...>;
value_type value;
bool get = false;
int N;
int c = 0;
value_type operator*(){
if(get) return value;
else{
input_tuple_helper(value, std::make_index_sequence<sizeof...(Args)>());
return value;
}
}
void operator++(){
++c;
get = false;
}
bool operator!=(iter &) const {
return c < N;
}
iter(int N): N(N){}
};
int N;
public:
InputTuples(int N): N(N){}
iter begin() const {return iter(N);}
iter end() const {return iter(N);}
};
template <typename ... Args>
auto input_tuples(int N){
return InputTuples<Args ...>(N);
}
/**
* @title modint
* @docs mint.md
*/
template <uint32_t M> class ModInt{
public:
constexpr static uint32_t MOD = M;
uint64_t val;
constexpr ModInt(): val(0){}
constexpr ModInt(int64_t n){
if(n >= M) val = n % M;
else if(n < 0) val = n % M + M;
else val = n;
}
inline constexpr auto operator+(const ModInt &a) const {return ModInt(val + a.val);}
inline constexpr auto operator-(const ModInt &a) const {return ModInt(val - a.val);}
inline constexpr auto operator*(const ModInt &a) const {return ModInt(val * a.val);}
inline constexpr auto operator/(const ModInt &a) const {return ModInt(val * a.inv().val);}
inline constexpr auto& operator=(const ModInt &a){val = a.val; return *this;}
inline constexpr auto& operator+=(const ModInt &a){if((val += a.val) >= M) val -= M; return *this;}
inline constexpr auto& operator-=(const ModInt &a){if(val < a.val) val += M; val -= a.val; return *this;}
inline constexpr auto& operator*=(const ModInt &a){(val *= a.val) %= M; return *this;}
inline constexpr auto& operator/=(const ModInt &a){(val *= a.inv().val) %= M; return *this;}
inline constexpr bool operator==(const ModInt &a) const {return val == a.val;}
inline constexpr bool operator!=(const ModInt &a) const {return val != a.val;}
inline constexpr auto& operator++(){*this += 1; return *this;}
inline constexpr auto& operator--(){*this -= 1; return *this;}
inline constexpr auto operator++(int){auto t = *this; *this += 1; return t;}
inline constexpr auto operator--(int){auto t = *this; *this -= 1; return t;}
inline constexpr static ModInt power(int64_t n, int64_t p){
if(p < 0) return power(n, -p).inv();
int64_t ret = 1, e = n % M;
for(; p; (e *= e) %= M, p >>= 1) if(p & 1) (ret *= e) %= M;
return ret;
}
inline constexpr static ModInt inv(int64_t a){
int64_t b = M, u = 1, v = 0;
while(b){
int64_t t = a / b;
a -= t * b; std::swap(a,b);
u -= t * v; std::swap(u,v);
}
u %= M;
if(u < 0) u += M;
return u;
}
inline constexpr static auto frac(int64_t a, int64_t b){return ModInt(a) / ModInt(b);}
inline constexpr auto power(int64_t p) const {return power(val, p);}
inline constexpr auto inv() const {return inv(val);}
friend inline constexpr auto operator-(const ModInt &a){return ModInt(-a.val);}
friend inline constexpr auto operator+(int64_t a, const ModInt &b){return ModInt(a) + b;}
friend inline constexpr auto operator-(int64_t a, const ModInt &b){return ModInt(a) - b;}
friend inline constexpr auto operator*(int64_t a, const ModInt &b){return ModInt(a) * b;}
friend inline constexpr auto operator/(int64_t a, const ModInt &b){return ModInt(a) / b;}
friend std::istream& operator>>(std::istream &s, ModInt<M> &a){s >> a.val; return s;}
friend std::ostream& operator<<(std::ostream &s, const ModInt<M> &a){s << a.val; return s;}
template <int N>
inline static auto div(){
static auto value = inv(N);
return value;
}
explicit operator int32_t() const noexcept {return val;}
explicit operator int64_t() const noexcept {return val;}
};
/**
* @title NumberTheoreticTransform
* @docs ntt_convolution.md
*/
template <typename T, int PRIM_ROOT, int MAX_SIZE>
class NumberTheoreticTransform{
const int MAX_POWER;
std::vector<T> BASE, INV_BASE;
public:
NumberTheoreticTransform():
MAX_POWER(__builtin_ctz(MAX_SIZE)),
BASE(MAX_POWER + 1),
INV_BASE(MAX_POWER + 1)
{
static_assert((MAX_SIZE & (MAX_SIZE - 1)) == 0, "MAX_SIZE must be power of 2.");
T t = T::power(PRIM_ROOT, (T::MOD-1) >> (MAX_POWER + 2));
T s = t.inv();
for(int i = MAX_POWER - 1; i >= 0; --i){
t *= t;
s *= s;
BASE[i] = -t;
INV_BASE[i] = -s;
}
}
void run_ntt(std::vector<T> &f, bool INVERSE = false){
const int n = f.size();
assert((n & (n-1)) == 0 and n <= MAX_SIZE); // データ数は2の冪乗個
if(INVERSE){
for(int b = 1; b < n; b <<= 1){
T w = 1;
for(int j = 0, k = 1; j < n; j += 2 * b, ++k){
for(int i = 0; i < b; ++i){
const auto s = f[i+j];
const auto t = f[i+j+b];
f[i+j] = s + t;
f[i+j+b] = (s - t) * w;
}
w *= INV_BASE[__builtin_ctz(k)];
}
}
const T t = T::inv(n);
for(auto &x : f) x *= t;
}else{
for(int b = n >> 1; b; b >>= 1){
T w = 1;
for(int j = 0, k = 1; j < n; j += 2 * b, ++k){
for(int i = 0; i < b; ++i){
const auto s = f[i+j];
const auto t = f[i+j+b] * w;
f[i+j] = s + t;
f[i+j+b] = s - t;
}
w *= BASE[__builtin_ctz(k)];
}
}
}
}
template <typename U>
std::vector<T> run_convolution(std::vector<U> f, std::vector<U> g){
const int m = f.size() + g.size() - 1;
int n = 1;
while(n < m) n *= 2;
std::vector<T> f2(n), g2(n);
for(int i = 0; i < (int)f.size(); ++i) f2[i] = f[i];
for(int i = 0; i < (int)g.size(); ++i) g2[i] = g[i];
run_ntt(f2);
run_ntt(g2);
for(int i = 0; i < n; ++i) f2[i] *= g2[i];
run_ntt(f2, true);
return f2;
}
};
constexpr int mod = 998244353;
using mint = ModInt<mod>;
int main(){
std::cin.tie(0);
std::ios::sync_with_stdio(false);
int N, Q; std::cin >> N >> Q;
auto A = input_vector<int>(N);
std::vector<int> ord(N);
std::iota(ord.begin(), ord.end(), 0);
std::sort(ord.begin(), ord.end(), [&](int i, int j){return A[i] < A[j];});
std::vector<int> c(A);
std::sort(c.begin(), c.end());
auto ntt = NumberTheoreticTransform<mint, 3, 1 << 20>();
std::vector<mint> right(N+1);
std::vector<std::vector<mint>> left(N+1);
right[0] = 1;
for(int i = 0; i < N; ++i){
right[i + 1] = A[ord[i]];
}
for(int i = 0; i < N; ++i){
right[i + 1] = right[i + 1] * right[i];
}
left[N] = {1};
for(int i = 0; i < N; ++i){
left[i] = {A[ord[i]] - 1, 1};
}
for(int i = N; i > 0; --i){
left[i - 1] = ntt.run_convolution(left[i - 1], left[i]);
if((int)left[i - 1].size() > N + 1) left[i - 1].resize(N + 1);
}
std::vector<std::vector<mint>> f(N+1);
for(int i = 0; i < N + 1; ++i){
f[i] = ntt.run_convolution({right[i]}, left[i]);
f[i].resize(N + 1);
}
for(auto [l, r, p] : input_tuples<int, int, int>(Q)){
int ans = 0;
for(int i = l; i <= r; ++i){
int j = std::lower_bound(c.begin(), c.end(), i) - c.begin();
ans ^= f[j][p].val;
}
ans %= mod;
std::cout << ans << "\n";
}
return 0;
}