Problem:
K Umg Kart
問題文
umgくんは車のレース大会を主催することにしました。このレースでは、距離が $L$ のコース上を走って競います。スタート位置を位置 $0$ とし、スタート位置からゴールに向かって $x$ だけ離れた位置を位置 $x$ と呼ぶことにします。
てんぷらくんはこのレース大会に参加することにしました。今回のレースではてんぷらくんを含め $N$ 人の選手が参加することになっており、 $N$ 人の選手には$1$から$N$までの番号がついています。てんぷらくんは選手$1$です。
さて、レースが始まると、各選手はスタート位置から一斉に走り出します。選手 $i$ の車は距離 $1$ 進むのに $t_i$ 秒かかります。umgくんはこのままではレースが面白くないと思い、 $M$ 個のアイテムボックスをコース上に配置することにしました。アイテムボックス $j$ の概要は次の通りです。
位置 $x_j$ (整数)にある。
各選手は、位置 $x_j$ に来たら、必ずアイテムボックス $j$ を取得する。アイテムボックス $j$ は各選手について $1$ つずつ用意されている。
アイテムボックス $j$ には確率 $\frac{p_j}{100}$ が定められている。選手 $i$ がアイテムボックス $j$ をとると、次のアイテムボックスを取るまで(またはゴール位置まで)、 $\frac{p_j}{100}$ の確率で距離 $1$ 進むのにかかる時間が $t_i+D$ 秒になり(減速する)、 $1-\frac{p_j}{100}$ の確率で距離 $1$ 進むのにかかる時間が $t_i-D$ 秒になる(加速する)。
ただし、 $D$ は $ D \lt \min _ i (t_i)$ を満たす。
レースの順位は、ゴールである位置 $L$ にたどり着いた順番で決まります。最初にゴールについた選手が $1$ 位で、最後にゴールについた選手が $N$ 位です。同着の場合は番号の小さい選手から順に先に到着したとみなします。
てんぷらくん(選手 $1$ )の順位の期待値を求めてください。答えが有理数になることが問題の制約から証明できるので、答えは${\rm modulo} \ 998244353$ で出力してください。正確には、期待値が既約分数 $\frac{P}{Q}$ で表されるとき、 $R \times Q = P, 0\leq R \lt 998244353$ を満たす $R$ が一意に定まるので、その $R$ を出力してください。
入力
入力は以下の形式で標準入力から与えられる。
$N$ $L$
$t_1$ $t_2$ $\cdots$ $t_N$
$M$ $D$
$x_1$ $p_1$
$x_2$ $p_2$
$\vdots$
$x_M$ $p_M$
制約
入力はすべて整数である。
$2 \leq N \leq 10^5$
$2 \leq L \leq 10^5$
$2 \leq t_i \leq 10^5$
$1 \leq M \leq L-1$
$1 \leq D \lt \min _ i (t_i)$
$0 \leq X_1 \lt X_2 \lt \cdots \lt X_M \leq L-1$
$0 \leq p_j \leq 100$
入力はすべて整数である。
出力
答えを 1 行に出力せよ。
入力例1
2 2
5 4
1 2
1 50
出力例1
249561090
てんぷらくん(選手 $1$ )の順位は、てんぷらくんがアイテムボックス $1$ で加速し、選手 $2$ がアイテムボックス $1$ で減速したときのみ $1$ 、それ以外のときは $2$ です。
よって、順位の期待値は $1 \times \frac{1}{4} + 2 \times \frac{3}{4} = \frac{7}{4}$ です。 $249561090 \times 4 = 7 \ (\mathrm{mod}\ 998244353)$ なので、 $249561090$ を出力します。
入力例2
5 20
224 2 3 4 5
3 1
3 50
11 25
17 75
出力例2
5
レースにおいては適切なマシンを選ぶことも大切です。
入力例3
2 2
10 10
1 1
0 0
出力例3
1
同時刻にゴールした場合は、番号の小さい選手が順位が上になることに注意してください。
入力例4
8 22
19 18 13 10 12 10 20 17
10 3
1 50
2 19
3 17
4 79
5 54
6 76
7 64
8 69
9 98
10 9
出力例4
410169619

Submitted solutions:

code_snippet: #include <iostream>
#include <iomanip>
#include <cstdio>
#include <cmath>
#include <ctime>
#include <cstdlib>
#include <cassert>
#include <vector>
#include <list>
#include <stack>
#include <queue>
#include <deque>
#include <map>
#include <set>
#include <bitset>
#include <string>
#include <algorithm>
#include <utility>
#include <complex>
#include <unordered_set>
#include <unordered_map>
#define rep(x, s, t) for(ll x = (s); (x) <= (t); (x)++)
#define per(x, s, t) for(ll x = (s); (x) >= (t); (x)--)
#define reps(x, s) for(ll x = 0; (x) < (ll)(s).size(); (x)++)
#define chmin(x, y) (x) = min((x), (y))
#define chmax(x, y) (x) = max((x), (y))
#define sz(x) ((ll)(x).size())
#define ceil(x, y) (((x)+(y)-1) / (y))
#define all(x) (x).begin(),(x).end()
#define outl(...) dump_func(__VA_ARGS__)
#define outf(x) cout << fixed << setprecision(16) << (x) << endl
#define inf 1e18
const double PI = 3.1415926535897932384626433;

using namespace std;

typedef long long llint;
typedef long long ll;
typedef pair<ll, ll> P;

struct edge{
	ll to, cost;
	edge(){}
	edge(ll a, ll b){ to = a, cost = b;}
};
const int dx[] = {1, 0, -1, 0}, dy[] = {0, -1, 0, 1};

//const int mod = 1000000007;
const int mod = 998244353;

struct mint{
	int x;
	mint(ll y = 0){x = y; if(x < 0 || x >= mod) x = (x%mod+mod)%mod;}
	mint(const mint &ope) {x = ope.x;}
	
	mint operator-(){return mint(-x);}
	mint operator+(const mint &ope){return mint(x) += ope;}
	mint operator-(const mint &ope){return mint(x) -= ope;}
	mint operator*(const mint &ope){return mint(x) *= ope;}
	mint operator/(const mint &ope){return mint(x) /= ope;}
	mint& operator+=(const mint &ope){
		x += ope.x;
		if(x >= mod) x -= mod;
		return *this;
	}
	mint& operator-=(const mint &ope){
		x += mod - ope.x;
		if(x >= mod) x -= mod;
		return *this;
	}
	mint& operator*=(const mint &ope){
		ll tmp = x;
		tmp *= ope.x, tmp %= mod;
		x = tmp;
		return *this;
	}
	mint& operator/=(const mint &ope){
		ll n = mod-2; mint mul = ope;
		while(n){
			if(n & 1) *this *= mul;
			mul *= mul;
			n >>= 1;
		}
		return *this;
	}
	mint inverse(){return mint(1) / *this;}
	bool operator ==(const mint &ope){return x == ope.x;}
	bool operator !=(const mint &ope){return x != ope.x;}
	bool operator <(const mint &ope){return x < ope.x;}
};
mint modpow(mint a, ll n){
	if(n == 0) return mint(1);
	if(n % 2) return a * modpow(a, n-1);
	else return modpow(a*a, n/2);
}
istream& operator >>(istream &is, mint &ope){
	ll t; is >> t, ope.x = t;
	return is;
}
ostream& operator <<(ostream &os, mint &ope){return os << ope.x;}
ostream& operator <<(ostream &os, const mint &ope){return os << ope.x;}

vector<mint> fact, fact_inv;
void make_fact(int n){
	fact.resize(n+1), fact_inv.resize(n+1);
	fact[0] = mint(1); rep(i, 1, n) fact[i] = fact[i-1] * mint(i);
	fact_inv[n] = fact[n].inverse(); per(i, n-1, 0) fact_inv[i] = fact_inv[i+1] * mint(i+1);
}
mint comb(int n, int k){ if(n < 0 || k < 0 || n < k) return mint(0); return fact[n] * fact_inv[k] * fact_inv[n-k];}
mint perm(int n, int k){ return comb(n, k) * fact[k]; }

vector<int> prime, pvec;
void make_prime(int n){
	prime.resize(n+1);
	rep(i, 2, n){
		if(prime[i]) continue;
		for(int j = i; j <= n; j+=i) prime[j] = i;
	}
	rep(i, 2, n) if(prime[i] == i) pvec.push_back(i);
}

bool exceed(ll x, ll y, ll m){return x >= m / y + 1;}
void mark(){ cout << "*" << endl; }
void yes(){ cout << "YES" << endl; }
void no(){ cout << "NO" << endl; }
ll sgn(ll x){ if(x > 0) return 1; if(x < 0) return -1; return 0;}
ll gcd(ll a, ll b){if(b == 0) return a; return gcd(b, a%b);}
ll lcm(ll a, ll b){return a/gcd(a, b)*b;}
ll digitnum(ll x, ll b = 10){ll ret = 0; for(; x; x /= b) ret++; return ret;}
ll digitsum(ll x, ll b = 10){ll ret = 0; for(; x; x /= b) ret += x % b; return ret;}
string lltos(ll x){string ret; for(;x;x/=10) ret += x % 10 + '0'; reverse(ret.begin(), ret.end()); return ret;}
ll stoll(string &s){ll ret = 0; for(auto c : s) ret *= 10, ret += c - '0'; return ret;}
template<typename T>
void uniq(T &vec){ sort(vec.begin(), vec.end()); vec.erase(unique(vec.begin(), vec.end()), vec.end());}

template<class S, class T> pair<S, T>& operator+=(pair<S,T> &s, const pair<S,T> &t){
	s.first += t.first, s.second += t.second;
	return s;
}
template<class S, class T> pair<S, T>& operator-=(pair<S,T> &s, const pair<S,T> &t){
	s.first -= t.first, s.second -= t.second;
	return s;
}
template<class S, class T> pair<S, T> operator+(const pair<S,T> &s, const pair<S,T> &t){
	return pair<S,T>(s.first+t.first, s.second+t.second);
}
template<class S, class T> pair<S, T> operator-(const pair<S,T> &s, const pair<S,T> &t){
	return pair<S,T>(s.first-t.first, s.second-t.second);
}
template<typename T>
ostream& operator << (ostream& os, vector<T>& vec) {
	for(int i = 0; i < vec.size(); i++) os << vec[i] << (i + 1 == vec.size() ? "" : " ");
	return os;
}
template<typename T>
ostream& operator << (ostream& os, deque<T>& deq) {
	for(int i = 0; i < deq.size(); i++) os << deq[i] << (i + 1 == deq.size() ? "" : " ");
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, pair<T, U>& pair_var) {
	os << "(" << pair_var.first << ", " << pair_var.second << ")";
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, const pair<T, U>& pair_var) {
	os << "(" << pair_var.first << ", " << pair_var.second << ")";
	return os;
}
template<typename T, typename U>
ostream& operator << (ostream& os, map<T, U>& map_var) {
	for(typename map<T, U>::iterator itr = map_var.begin(); itr != map_var.end(); itr++) {
		os << "(" << itr->first << ", " << itr->second << ")";
		itr++; if(itr != map_var.end()) os << ","; itr--;
	}
	return os;
}
template<typename T>
ostream& operator << (ostream& os, set<T>& set_var) {
	for(typename set<T>::iterator itr = set_var.begin(); itr != set_var.end(); itr++) {
		os << *itr; ++itr; if(itr != set_var.end()) os << " "; itr--;
	}
	return os;
}
template<typename T>
ostream& operator << (ostream& os, multiset<T>& set_var) {
	for(typename multiset<T>::iterator itr = set_var.begin(); itr != set_var.end(); itr++) {
		os << *itr; ++itr; if(itr != set_var.end()) os << " "; itr--;
	}
	return os;
}
template<typename T>
void outa(T a[], ll s, ll t){rep(i, s, t){ cout << a[i]; if(i < t) cout << " ";}cout << endl;}
void dump_func(){cout << endl;}
template <class Head, class... Tail>
void dump_func(Head &&head, Tail &&... tail) {
	cout << head;
	if(sizeof...(Tail) > 0) cout << " ";
	dump_func(std::move(tail)...);
}

/*
{1224736769, 3}, // 2^24 * 73 + 1,
{1053818881, 7}, // 2^20 * 3 * 5 * 67 + 1
{1051721729, 6}, // 2^20 * 17 * 59 + 1
{1045430273, 3}, // 2^20 * 997 + 1
{1012924417, 5}, // 2^21 * 3 * 7 * 23 + 1
{1007681537, 3}, // 2^20 * 31^2 + 1
{1004535809, 3}, // 2^21 * 479 + 1
{998244353, 3},  // 2^23 * 7 * 17 + 1
{985661441, 3},  // 2^22 * 5 * 47 + 1
{976224257, 3},  // 2^20 * 7^2 * 19 + 1
{975175681, 17}, // 2^21 * 3 * 5 * 31 + 1
{962592769, 7},  // 2^21 * 3^3 * 17 + 1
{950009857, 7},  // 2^21 * 4 * 151 + 1
{943718401, 7},  // 2^22 * 3^2 * 5^2 + 1
{935329793, 3},  // 2^22 * 223 + 1
{924844033, 5},  // 2^21 * 3^2 * 7^2 + 1
{469762049, 3},  // 2^26 * 7 + 1
{167772161, 3},  // 2^25 * 5 + 1
*/

struct FFT_Convolution{
	typedef complex<double> C;
	
	FFT_Convolution(){};
	static int rev(int x, int n){
		int ret = 0;
		for(int i = 0; i < n; i++) ret <<= 1, ret |= (x>>i) & 1;
		return ret;
	}
	
	static void DFT(vector<C> &f, vector<C> &F, int n)
	{
		int N = 1<<n;
		F.resize(N);
		for(int i = 0; i < N; i++) F[rev(i, n)] = f[i];
		
		C a, b, x, z;
		for(int i = 1; i <= n; i++){
			int l = 1<<i;
			z = C(cos(2*PI/l), sin(2*PI/l));
			for(int j = 0; j < N/l; j++){
				x = C(1, 0);
				for(int k = 0; k < l/2; k++){
					a = F[j*l+k], b = F[j*l+k+l/2];
					F[j*l+k] = a + x * b;
					F[j*l+k+l/2] = a - x * b;
					x *= z;
				}
			}
		}
	}
	static void IDFT(vector<C> &F, vector<C> &f, int n)
	{
		int N = 1<<n;
		for(int i = 0; i < N; i++) f[rev(i, n)] = F[i];
		
		C a, b, x, z;
		for(int i = 1; i <= n; i++){
			int l = 1<<i;
			z = C(cos(2*PI/l), -sin(2*PI/l));
			for(int j = 0; j < N/l; j++){
				x = C(1, 0);
				for(int k = 0; k < l/2; k++){
					a = f[j*l+k], b = f[j*l+k+l/2];
					f[j*l+k] = a + x * b;
					f[j*l+k+l/2] = a - x * b;
					x *= z;
				}
			}
		}
		for(int i = 0; i < N; i++) f[i] /= N;
	}
	static ll round(C c){return (ll)(c.real()+0.5);}
	
	static void conv(vector<ll> f, vector<ll> g, vector<ll> &dest)
	{
		ll logf = 0, logg = 0, len = f.size() + g.size();
		for(int i = f.size(); i; i /= 2) logf++;
		for(int i = g.size(); i; i /= 2) logg++;
		
		ll n = max(logf, logg)+1, N = 1<<n;
		vector<C> f2(N), g2(N);
		for(int i = 0; i < N; i++){
			if(i < f.size()) f2[i] = C(f[i], 0);
			else f2[i] = C(0, 0);
		}
		for(int i = 0; i < N; i++){
			if(i < g.size()) g2[i] = C(g[i], 0);
			else g2[i] = C(0, 0);
		}
		
		vector<C> F, G;
		DFT(f2, F, n), DFT(g2, G, n);
		for(int i = 0; i < N; i++) F[i] *= G[i];
		IDFT(F, f2, n);
		
		dest.resize(len-1);
		for(int i = 0; i < dest.size(); i++) dest[i] = round(f2[i]);
	}
};

struct NTT_Convolution{
	NTT_Convolution(){};
	static int rev(int x, int n){
		int ret = 0;
		for(int i = 0; i < n; i++) ret <<= 1, ret |= (x>>i) & 1;
		return ret;
	}
	static void DFT(vector<mint> &f, vector<mint> &F, int n, mint root, bool inv = false)
	{
		int N = 1<<n;
		F.resize(N);
		for(int i = 0; i < N; i++) F[rev(i, n)] = f[i];
		if(inv) root = root.inverse();
		
		mint a, b, x, z;
		for(int i = 0; i < n; i++){
			int l = 1<<i;
			z = modpow(root, 1<<(n-(i+1)));
			for(int j = 0; j < N; j+=l*2){
				x = 1;
				for(int k = j; k < j+l; k++){
					a = F[k], b = F[k+l] * x;
					F[k] = a + b, F[k+l] = a - b, x *= z;
				}
			}
		}
		if(inv){
			mint Ninv = mint(N).inverse();
			for(int i = 0; i < N; i++) F[i] *= Ninv;
		}
	}
	static void conv(vector<mint> f, vector<mint> g, vector<mint> &dest)
	{
		ll logf = 0, logg = 0, len = f.size() + g.size();
		for(int i = f.size(); i; i /= 2) logf++;
		for(int i = g.size(); i; i /= 2) logg++;
		
		ll n = max(logf, logg)+1, N = 1<<n;
		f.resize(N), g.resize(N);
		mint root = modpow(mint(3), 119 * (1<<23-n));
		
		vector<mint> F, G;
		DFT(f, F, n, root), DFT(g, G, n, root);
		for(int i = 0; i < N; i++) F[i] *= G[i];
		DFT(F, f, n, root, true);
		
		f.resize(len-1);
		dest = f;
	}
};

struct ConvolutionMerge{
	int id;
	vector<vector<mint> > vec;
	priority_queue<P, vector<P>, greater<P> >Q;
	
	ConvolutionMerge(){init();}
	void init(){
		id = 0;
		vec.clear();
		while(Q.size()) Q.pop();
		vector<mint> f;
		f.push_back(mint(1));
		add(f);
	}
	void add(vector<mint> &f){
		Q.push(P(f.size(), id++));
		vec.push_back(f);
	}
	void calc(vector<mint> &dest){
		while(Q.size() >= 2){
			ll u = Q.top().second; Q.pop();
			ll v = Q.top().second; Q.pop();
			NTT_Convolution::conv(vec[u], vec[v], vec[u]);
			Q.push(P(vec[u].size(), u));
		}
		dest = vec[Q.top().second];
	}
};

llint n, L;
llint t[100005];
llint m, d;
llint x[100005], w[100005];
mint p[100005], sum[200005];
ConvolutionMerge cm;

int main(void)
{
	ios::sync_with_stdio(0);
	cin.tie(0);
	
	cin >> n >> L;
	for(int i = 1; i <= n; i++) cin >> t[i];
	cin >> m >> d;
	for(int i = 1; i <= m; i++) cin >> x[i] >> p[i];
	
	mint inv100 = mint(100).inverse();
	
	x[m+1] = L;
	for(int i = 1; i <= m; i++){
		w[i] = x[i+1] - x[i];
		p[i] *= inv100;
	}
	
	vector<mint> vec;
	for(int i = 1; i <= m; i++){
		vec.clear(), vec.resize(w[i]+1);
		vec[0] = mint(1) - p[i];
		vec[w[i]] = p[i];
		cm.add(vec);
	}
	cm.calc(vec);
	
	vector<mint> f(L+1), g(L+1);
	reps(i, vec) f[i] = vec[i], g[L-i] = vec[i];
	NTT_Convolution::conv(f, g, f);
	for(int i = 2*L; i >= 0; i--) sum[i] = sum[i+1] + f[i];
	
	mint ans = 1;
	for(int i = 2; i <= n; i++){
		llint b = (L*(t[1]-t[i])+2*d-1)/(2*d);
		if(L*(t[1]-t[i]) < 0) b = L*(t[1]-t[i])/(2*d);
		
		mint p = 0;
		if(b <= -L) p = 1;
		else if(b <= L) p = sum[b+L];
		ans += mint(1) - p;
	}
	outl(ans);
	
	return 0;
}
accuracy: 1
time_ms: 380
memory_kb: 26196
final_rank: 8

code_snippet: #include <bits/stdc++.h>


#include <algorithm>
#include <array>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

// @param n `0 <= n`
// @return minimum non-negative `x` s.t. `n <= 2**x`
int ceil_pow2(int n) {
    int x = 0;
    while ((1U << x) < (unsigned int)(n)) x++;
    return x;
}

// @param n `1 <= n`
// @return minimum non-negative `x` s.t. `(n & (1 << x)) != 0`
int bsf(unsigned int n) {
#ifdef _MSC_VER
    unsigned long index;
    _BitScanForward(&index, n);
    return index;
#else
    return __builtin_ctz(n);
#endif
}

}  // namespace internal

}  // namespace atcoder



#include <utility>

namespace atcoder {

namespace internal {

// @param m `1 <= m`
// @return x mod m
constexpr long long safe_mod(long long x, long long m) {
    x %= m;
    if (x < 0) x += m;
    return x;
}

// Fast moduler by barrett reduction
// Reference: https://en.wikipedia.org/wiki/Barrett_reduction
// NOTE: reconsider after Ice Lake
struct barrett {
    unsigned int _m;
    unsigned long long im;

    // @param m `1 <= m`
    barrett(unsigned int m) : _m(m), im((unsigned long long)(-1) / m + 1) {}

    // @return m
    unsigned int umod() const { return _m; }

    // @param a `0 <= a < m`
    // @param b `0 <= b < m`
    // @return `a * b % m`
    unsigned int mul(unsigned int a, unsigned int b) const {
        // [1] m = 1
        // a = b = im = 0, so okay

        // [2] m >= 2
        // im = ceil(2^64 / m)
        // -> im * m = 2^64 + r (0 <= r < m)
        // let z = a*b = c*m + d (0 <= c, d < m)
        // a*b * im = (c*m + d) * im = c*(im*m) + d*im = c*2^64 + c*r + d*im
        // c*r + d*im < m * m + m * im < m * m + 2^64 + m <= 2^64 + m * (m + 1) < 2^64 * 2
        // ((ab * im) >> 64) == c or c + 1
        unsigned long long z = a;
        z *= b;
#ifdef _MSC_VER
        unsigned long long x;
        _umul128(z, im, &x);
#else
        unsigned long long x =
            (unsigned long long)(((unsigned __int128)(z)*im) >> 64);
#endif
        unsigned int v = (unsigned int)(z - x * _m);
        if (_m <= v) v += _m;
        return v;
    }
};

// @param n `0 <= n`
// @param m `1 <= m`
// @return `(x ** n) % m`
constexpr long long pow_mod_constexpr(long long x, long long n, int m) {
    if (m == 1) return 0;
    unsigned int _m = (unsigned int)(m);
    unsigned long long r = 1;
    unsigned long long y = safe_mod(x, m);
    while (n) {
        if (n & 1) r = (r * y) % _m;
        y = (y * y) % _m;
        n >>= 1;
    }
    return r;
}

// Reference:
// M. Forisek and J. Jancina,
// Fast Primality Testing for Integers That Fit into a Machine Word
// @param n `0 <= n`
constexpr bool is_prime_constexpr(int n) {
    if (n <= 1) return false;
    if (n == 2 || n == 7 || n == 61) return true;
    if (n % 2 == 0) return false;
    long long d = n - 1;
    while (d % 2 == 0) d /= 2;
    for (long long a : {2, 7, 61}) {
        long long t = d;
        long long y = pow_mod_constexpr(a, t, n);
        while (t != n - 1 && y != 1 && y != n - 1) {
            y = y * y % n;
            t <<= 1;
        }
        if (y != n - 1 && t % 2 == 0) {
            return false;
        }
    }
    return true;
}
template <int n> constexpr bool is_prime = is_prime_constexpr(n);

// @param b `1 <= b`
// @return pair(g, x) s.t. g = gcd(a, b), xa = g (mod b), 0 <= x < b/g
constexpr std::pair<long long, long long> inv_gcd(long long a, long long b) {
    a = safe_mod(a, b);
    if (a == 0) return {b, 0};

    // Contracts:
    // [1] s - m0 * a = 0 (mod b)
    // [2] t - m1 * a = 0 (mod b)
    // [3] s * |m1| + t * |m0| <= b
    long long s = b, t = a;
    long long m0 = 0, m1 = 1;

    while (t) {
        long long u = s / t;
        s -= t * u;
        m0 -= m1 * u;  // |m1 * u| <= |m1| * s <= b

        // [3]:
        // (s - t * u) * |m1| + t * |m0 - m1 * u|
        // <= s * |m1| - t * u * |m1| + t * (|m0| + |m1| * u)
        // = s * |m1| + t * |m0| <= b

        auto tmp = s;
        s = t;
        t = tmp;
        tmp = m0;
        m0 = m1;
        m1 = tmp;
    }
    // by [3]: |m0| <= b/g
    // by g != b: |m0| < b/g
    if (m0 < 0) m0 += b / s;
    return {s, m0};
}

// Compile time primitive root
// @param m must be prime
// @return primitive root (and minimum in now)
constexpr int primitive_root_constexpr(int m) {
    if (m == 2) return 1;
    if (m == 167772161) return 3;
    if (m == 469762049) return 3;
    if (m == 754974721) return 11;
    if (m == 998244353) return 3;
    int divs[20] = {};
    divs[0] = 2;
    int cnt = 1;
    int x = (m - 1) / 2;
    while (x % 2 == 0) x /= 2;
    for (int i = 3; (long long)(i)*i <= x; i += 2) {
        if (x % i == 0) {
            divs[cnt++] = i;
            while (x % i == 0) {
                x /= i;
            }
        }
    }
    if (x > 1) {
        divs[cnt++] = x;
    }
    for (int g = 2;; g++) {
        bool ok = true;
        for (int i = 0; i < cnt; i++) {
            if (pow_mod_constexpr(g, (m - 1) / divs[i], m) == 1) {
                ok = false;
                break;
            }
        }
        if (ok) return g;
    }
}
template <int m> constexpr int primitive_root = primitive_root_constexpr(m);

}  // namespace internal

}  // namespace atcoder


#include <cassert>
#include <numeric>
#include <type_traits>

namespace atcoder {

namespace internal {

#ifndef _MSC_VER
template <class T>
using is_signed_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value ||
                                  std::is_same<T, __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int128 =
    typename std::conditional<std::is_same<T, __uint128_t>::value ||
                                  std::is_same<T, unsigned __int128>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using make_unsigned_int128 =
    typename std::conditional<std::is_same<T, __int128_t>::value,
                              __uint128_t,
                              unsigned __int128>;

template <class T>
using is_integral = typename std::conditional<std::is_integral<T>::value ||
                                                  is_signed_int128<T>::value ||
                                                  is_unsigned_int128<T>::value,
                                              std::true_type,
                                              std::false_type>::type;

template <class T>
using is_signed_int = typename std::conditional<(is_integral<T>::value &&
                                                 std::is_signed<T>::value) ||
                                                    is_signed_int128<T>::value,
                                                std::true_type,
                                                std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<(is_integral<T>::value &&
                               std::is_unsigned<T>::value) ||
                                  is_unsigned_int128<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<
    is_signed_int128<T>::value,
    make_unsigned_int128<T>,
    typename std::conditional<std::is_signed<T>::value,
                              std::make_unsigned<T>,
                              std::common_type<T>>::type>::type;

#else

template <class T> using is_integral = typename std::is_integral<T>;

template <class T>
using is_signed_int =
    typename std::conditional<is_integral<T>::value && std::is_signed<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using is_unsigned_int =
    typename std::conditional<is_integral<T>::value &&
                                  std::is_unsigned<T>::value,
                              std::true_type,
                              std::false_type>::type;

template <class T>
using to_unsigned = typename std::conditional<is_signed_int<T>::value,
                                              std::make_unsigned<T>,
                                              std::common_type<T>>::type;

#endif

template <class T>
using is_signed_int_t = std::enable_if_t<is_signed_int<T>::value>;

template <class T>
using is_unsigned_int_t = std::enable_if_t<is_unsigned_int<T>::value>;

template <class T> using to_unsigned_t = typename to_unsigned<T>::type;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <numeric>
#include <type_traits>

#ifdef _MSC_VER
#include <intrin.h>
#endif

namespace atcoder {

namespace internal {

struct modint_base {};
struct static_modint_base : modint_base {};

template <class T> using is_modint = std::is_base_of<modint_base, T>;
template <class T> using is_modint_t = std::enable_if_t<is_modint<T>::value>;

}  // namespace internal

template <int m, std::enable_if_t<(1 <= m)>* = nullptr>
struct static_modint : internal::static_modint_base {
    using mint = static_modint;

  public:
    static constexpr int mod() { return m; }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    static_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    static_modint(T v) {
        long long x = (long long)(v % (long long)(umod()));
        if (x < 0) x += umod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    static_modint(T v) {
        _v = (unsigned int)(v % umod());
    }
    static_modint(bool v) { _v = ((unsigned int)(v) % umod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v -= rhs._v;
        if (_v >= umod()) _v += umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        unsigned long long z = _v;
        z *= rhs._v;
        _v = (unsigned int)(z % umod());
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        if (prime) {
            assert(_v);
            return pow(umod() - 2);
        } else {
            auto eg = internal::inv_gcd(_v, m);
            assert(eg.first == 1);
            return eg.second;
        }
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static constexpr unsigned int umod() { return m; }
    static constexpr bool prime = internal::is_prime<m>;
};

template <int id> struct dynamic_modint : internal::modint_base {
    using mint = dynamic_modint;

  public:
    static int mod() { return (int)(bt.umod()); }
    static void set_mod(int m) {
        assert(1 <= m);
        bt = internal::barrett(m);
    }
    static mint raw(int v) {
        mint x;
        x._v = v;
        return x;
    }

    dynamic_modint() : _v(0) {}
    template <class T, internal::is_signed_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        long long x = (long long)(v % (long long)(mod()));
        if (x < 0) x += mod();
        _v = (unsigned int)(x);
    }
    template <class T, internal::is_unsigned_int_t<T>* = nullptr>
    dynamic_modint(T v) {
        _v = (unsigned int)(v % mod());
    }
    dynamic_modint(bool v) { _v = ((unsigned int)(v) % mod()); }

    unsigned int val() const { return _v; }

    mint& operator++() {
        _v++;
        if (_v == umod()) _v = 0;
        return *this;
    }
    mint& operator--() {
        if (_v == 0) _v = umod();
        _v--;
        return *this;
    }
    mint operator++(int) {
        mint result = *this;
        ++*this;
        return result;
    }
    mint operator--(int) {
        mint result = *this;
        --*this;
        return result;
    }

    mint& operator+=(const mint& rhs) {
        _v += rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator-=(const mint& rhs) {
        _v += mod() - rhs._v;
        if (_v >= umod()) _v -= umod();
        return *this;
    }
    mint& operator*=(const mint& rhs) {
        _v = bt.mul(_v, rhs._v);
        return *this;
    }
    mint& operator/=(const mint& rhs) { return *this = *this * rhs.inv(); }

    mint operator+() const { return *this; }
    mint operator-() const { return mint() - *this; }

    mint pow(long long n) const {
        assert(0 <= n);
        mint x = *this, r = 1;
        while (n) {
            if (n & 1) r *= x;
            x *= x;
            n >>= 1;
        }
        return r;
    }
    mint inv() const {
        auto eg = internal::inv_gcd(_v, mod());
        assert(eg.first == 1);
        return eg.second;
    }

    friend mint operator+(const mint& lhs, const mint& rhs) {
        return mint(lhs) += rhs;
    }
    friend mint operator-(const mint& lhs, const mint& rhs) {
        return mint(lhs) -= rhs;
    }
    friend mint operator*(const mint& lhs, const mint& rhs) {
        return mint(lhs) *= rhs;
    }
    friend mint operator/(const mint& lhs, const mint& rhs) {
        return mint(lhs) /= rhs;
    }
    friend bool operator==(const mint& lhs, const mint& rhs) {
        return lhs._v == rhs._v;
    }
    friend bool operator!=(const mint& lhs, const mint& rhs) {
        return lhs._v != rhs._v;
    }

  private:
    unsigned int _v;
    static internal::barrett bt;
    static unsigned int umod() { return bt.umod(); }
};
template <int id> internal::barrett dynamic_modint<id>::bt = 998244353;

using modint998244353 = static_modint<998244353>;
using modint1000000007 = static_modint<1000000007>;
using modint = dynamic_modint<-1>;

namespace internal {

template <class T>
using is_static_modint = std::is_base_of<internal::static_modint_base, T>;

template <class T>
using is_static_modint_t = std::enable_if_t<is_static_modint<T>::value>;

template <class> struct is_dynamic_modint : public std::false_type {};
template <int id>
struct is_dynamic_modint<dynamic_modint<id>> : public std::true_type {};

template <class T>
using is_dynamic_modint_t = std::enable_if_t<is_dynamic_modint<T>::value>;

}  // namespace internal

}  // namespace atcoder

#include <cassert>
#include <type_traits>
#include <vector>

namespace atcoder {

namespace internal {

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
void butterfly(std::vector<mint>& a) {
    static constexpr int g = internal::primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = internal::ceil_pow2(n);

    static bool first = true;
    static mint sum_e[30];  // sum_e[i] = ies[0] * ... * ies[i - 1] * es[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i < cnt2 - 2; i++) {
            sum_e[i] = es[i] * now;
            now *= ies[i];
        }
    }
    for (int ph = 1; ph <= h; ph++) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint now = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p] * now;
                a[i + offset] = l + r;
                a[i + offset + p] = l - r;
            }
            now *= sum_e[bsf(~(unsigned int)(s))];
        }
    }
}

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
void butterfly_inv(std::vector<mint>& a) {
    static constexpr int g = internal::primitive_root<mint::mod()>;
    int n = int(a.size());
    int h = internal::ceil_pow2(n);

    static bool first = true;
    static mint sum_ie[30];  // sum_ie[i] = es[0] * ... * es[i - 1] * ies[i]
    if (first) {
        first = false;
        mint es[30], ies[30];  // es[i]^(2^(2+i)) == 1
        int cnt2 = bsf(mint::mod() - 1);
        mint e = mint(g).pow((mint::mod() - 1) >> cnt2), ie = e.inv();
        for (int i = cnt2; i >= 2; i--) {
            // e^(2^i) == 1
            es[i - 2] = e;
            ies[i - 2] = ie;
            e *= e;
            ie *= ie;
        }
        mint now = 1;
        for (int i = 0; i < cnt2 - 2; i++) {
            sum_ie[i] = ies[i] * now;
            now *= es[i];
        }
    }

    for (int ph = h; ph >= 1; ph--) {
        int w = 1 << (ph - 1), p = 1 << (h - ph);
        mint inow = 1;
        for (int s = 0; s < w; s++) {
            int offset = s << (h - ph + 1);
            for (int i = 0; i < p; i++) {
                auto l = a[i + offset];
                auto r = a[i + offset + p];
                a[i + offset] = l + r;
                a[i + offset + p] =
                    (unsigned long long)(mint::mod() + l.val() - r.val()) *
                    inow.val();
            }
            inow *= sum_ie[bsf(~(unsigned int)(s))];
        }
    }
}

}  // namespace internal

template <class mint, internal::is_static_modint_t<mint>* = nullptr>
std::vector<mint> convolution(std::vector<mint> a, std::vector<mint> b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};
    if (std::min(n, m) <= 60) {
        if (n < m) {
            std::swap(n, m);
            std::swap(a, b);
        }
        std::vector<mint> ans(n + m - 1);
        for (int i = 0; i < n; i++) {
            for (int j = 0; j < m; j++) {
                ans[i + j] += a[i] * b[j];
            }
        }
        return ans;
    }
    int z = 1 << internal::ceil_pow2(n + m - 1);
    a.resize(z);
    internal::butterfly(a);
    b.resize(z);
    internal::butterfly(b);
    for (int i = 0; i < z; i++) {
        a[i] *= b[i];
    }
    internal::butterfly_inv(a);
    a.resize(n + m - 1);
    mint iz = mint(z).inv();
    for (int i = 0; i < n + m - 1; i++) a[i] *= iz;
    return a;
}

template <unsigned int mod = 998244353,
          class T,
          std::enable_if_t<internal::is_integral<T>::value>* = nullptr>
std::vector<T> convolution(const std::vector<T>& a, const std::vector<T>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    using mint = static_modint<mod>;
    std::vector<mint> a2(n), b2(m);
    for (int i = 0; i < n; i++) {
        a2[i] = mint(a[i]);
    }
    for (int i = 0; i < m; i++) {
        b2[i] = mint(b[i]);
    }
    auto c2 = convolution(move(a2), move(b2));
    std::vector<T> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        c[i] = c2[i].val();
    }
    return c;
}

std::vector<long long> convolution_ll(const std::vector<long long>& a,
                                      const std::vector<long long>& b) {
    int n = int(a.size()), m = int(b.size());
    if (!n || !m) return {};

    static constexpr unsigned long long MOD1 = 754974721;  // 2^24
    static constexpr unsigned long long MOD2 = 167772161;  // 2^25
    static constexpr unsigned long long MOD3 = 469762049;  // 2^26
    static constexpr unsigned long long M2M3 = MOD2 * MOD3;
    static constexpr unsigned long long M1M3 = MOD1 * MOD3;
    static constexpr unsigned long long M1M2 = MOD1 * MOD2;
    static constexpr unsigned long long M1M2M3 = MOD1 * MOD2 * MOD3;

    static constexpr unsigned long long i1 =
        internal::inv_gcd(MOD2 * MOD3, MOD1).second;
    static constexpr unsigned long long i2 =
        internal::inv_gcd(MOD1 * MOD3, MOD2).second;
    static constexpr unsigned long long i3 =
        internal::inv_gcd(MOD1 * MOD2, MOD3).second;

    auto c1 = convolution<MOD1>(a, b);
    auto c2 = convolution<MOD2>(a, b);
    auto c3 = convolution<MOD3>(a, b);

    std::vector<long long> c(n + m - 1);
    for (int i = 0; i < n + m - 1; i++) {
        unsigned long long x = 0;
        x += (c1[i] * i1) % MOD1 * M2M3;
        x += (c2[i] * i2) % MOD2 * M1M3;
        x += (c3[i] * i3) % MOD3 * M1M2;
        // B = 2^63, -B <= x, r(real value) < B
        // (x, x - M, x - 2M, or x - 3M) = r (mod 2B)
        // r = c1[i] (mod MOD1)
        // focus on MOD1
        // r = x, x - M', x - 2M', x - 3M' (M' = M % 2^64) (mod 2B)
        // r = x,
        //     x - M' + (0 or 2B),
        //     x - 2M' + (0, 2B or 4B),
        //     x - 3M' + (0, 2B, 4B or 6B) (without mod!)
        // (r - x) = 0, (0)
        //           - M' + (0 or 2B), (1)
        //           -2M' + (0 or 2B or 4B), (2)
        //           -3M' + (0 or 2B or 4B or 6B) (3) (mod MOD1)
        // we checked that
        //   ((1) mod MOD1) mod 5 = 2
        //   ((2) mod MOD1) mod 5 = 3
        //   ((3) mod MOD1) mod 5 = 4
        long long diff =
            c1[i] - internal::safe_mod((long long)(x), (long long)(MOD1));
        if (diff < 0) diff += MOD1;
        static constexpr unsigned long long offset[5] = {
            0, 0, M1M2M3, 2 * M1M2M3, 3 * M1M2M3};
        x -= offset[diff % 5];
        c[i] = x;
    }

    return c;
}

}  // namespace atcoder


#define For(i, a, b) for (int(i) = (int)(a); (i) < (int)(b); ++(i))
#define rFor(i, a, b) for (int(i) = (int)(a)-1; (i) >= (int)(b); --(i))
#define rep(i, n) For((i), 0, (n))
#define rrep(i, n) rFor((i), (n), 0)
#define fi first
#define se second

using namespace std;

typedef long long lint;
typedef unsigned long long ulint;
typedef pair<int, int> pii;
typedef pair<lint, lint> pll;

template <class T>
bool chmax(T &a, const T &b) {
    if (a < b) {
        a = b;
        return true;
    }
    return false;
}
template <class T>
bool chmin(T &a, const T &b) {
    if (a > b) {
        a = b;
        return true;
    }
    return false;
}

template <class T>
T div_floor(T a, T b) {
    if (b < 0) a *= -1, b *= -1;
    return a >= 0 ? a / b : (a + 1) / b - 1;
}
template <class T>
T div_ceil(T a, T b) {
    if (b < 0) a *= -1, b *= -1;
    return a > 0 ? (a - 1) / b + 1 : a / b;
}

template <typename T>
struct coord_comp {
    vector<T> v;
    bool sorted = false;

    coord_comp() {}

    int size() { return v.size(); }

    void add(T x) { v.push_back(x); }

    void build() {
        sort(v.begin(), v.end());
        v.erase(unique(v.begin(), v.end()), v.end());
        sorted = true;
    }

    int get_idx(T x) {
        assert(sorted);
        return lower_bound(v.begin(), v.end(), x) - v.begin();
    }
};

constexpr lint mod = 1000000007;
constexpr lint INF = mod * mod;
constexpr int MAX = 200010;

using namespace atcoder;
using mint = modint998244353;
using poly = vector<mint>;

int main() {
    int n;
    lint L;
    scanf("%d%lld", &n, &L);
    lint t[n];
    rep(i, n) scanf("%lld", &t[i]);
    int m;
    lint D;
    scanf("%d%lld", &m, &D);
    int x[m + 1];
    mint p[m];
    mint inv100 = mint(100).inv();
    rep(i, m) {
        int tmp;
        scanf("%d%d", &x[i], &tmp);
        p[i] = mint(tmp) * inv100;
    }
    x[m] = L;

    auto cmp = [&](const poly &a, const poly &b) {
        return a.size() > b.size();
    };
    priority_queue<poly, vector<poly>, decltype(cmp)> que(cmp);
    rep(i, m) {
        mint a = p[i] * (mint(1) - p[i]);
        mint b = p[i].pow(2) + (mint(1) - p[i]).pow(2);
        poly v(2 * (x[i + 1] - x[i]) + 1);
        v[0] = v[2 * (x[i + 1] - x[i])] = a;
        v[x[i + 1] - x[i]] = b;
        que.push(v);
    }
    while (que.size() >= 2) {
        auto a = que.top();
        que.pop();
        auto b = que.top();
        que.pop();
        que.push(convolution(a, b));
    }
    auto a = que.top();
    rrep(i, a.size() - 1) a[i] += a[i + 1];

    mint ans = 1;
    For(i, 1, n) {
        lint k = div_floor(L * (t[i] - t[0]), 2 * D) + 1 + L - x[0];
        if (k < (int)a.size()) ans += a[max(0LL, k)];
    }
    printf("%u\n", ans.val());
}
accuracy: 1
time_ms: 220
memory_kb: 14212
final_rank: 1

code_snippet: #include <bits/stdc++.h>
using namespace std;

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};
using mint = ModInt<>;

template <int mod = 998244353>
struct NTT {
  int base, maxb, root;
  vector<int> rv, roots, invr;
  NTT() : base(1), rv({0, 1}), roots({0, 1}), invr({0, 1}) {
    assert(mod >= 3 && mod & 1);
    int tmp = mod - 1;
    maxb = 0;
    while (!(tmp & 1)) tmp >>= 1, ++maxb;
    root = 2;
    while (mpow(root, (mod - 1) >> 1) == 1) ++root;
    assert(mpow(root, mod - 1) == 1);
    root = mpow(root, (mod - 1) >> maxb);
  }

  inline int mpow(int x, int n) {
    int res = 1;
    while (n) {
      if (n & 1) res = mul(res, x);
      x = mul(x, x);
      n >>= 1;
    }
    return res;
  }

  inline int inv(int x) {
    assert(x != 0);
    return mpow(x, mod - 2);
  }

  inline int add(int x, int y) {
    if ((x += y) >= mod) x -= mod;
    return x;
  }

  inline int mul(int x, int y) { return (int)(1LL * x * y % mod); }

  void ensure_base(int nb) {
    if (nb <= base) return;
    rv.resize(1 << nb);
    roots.resize(1 << nb);
    invr.resize(1 << nb);
    for (int i = 0; i < (1 << nb); ++i)
      rv[i] = (rv[i >> 1] >> 1) + ((i & 1) << (nb - 1));
    assert(nb <= maxb);
    while (base < nb) {
      int z = mpow(root, 1 << (maxb - 1 - base)), invz = inv(z);
      for (int i = 1 << (base - 1); i < (1 << base); ++i) {
        roots[i << 1] = roots[i];
        roots[(i << 1) + 1] = mul(roots[i], z);
        invr[i << 1] = invr[i];
        invr[(i << 1) + 1] = mul(invr[i], invz);
      }
      ++base;
    }
  }
  void ntt(vector<int> &a, int n, bool sg = 0) {
    assert((n & (n - 1)) == 0);
    int dif = base - __builtin_ctz(n);
    for (int i = 0; i < n; ++i)
      if (i < (rv[i] >> dif)) swap(a[i], a[rv[i] >> dif]);
    for (int k = 1; k < n; k <<= 1)
      for (int i = 0; i < n; i += 2 * k)
        for (int j = 0; j < k; ++j) {
          int z = mul(a[i + j + k], (sg ? roots[j + k] : invr[j + k]));
          a[i + j + k] = add(a[i + j], mod - z);
          a[i + j] = add(a[i + j], z);
        }
    int invn = inv(n);
    if (sg)
      for (int i = 0; i < n; ++i) a[i] = mul(a[i], invn);
  }
  template <class T>
  vector<T> multiply(const vector<T> &a, const vector<T> &b) {
    int need = a.size() + b.size() - 1;
    int nb = 1;
    while ((1 << nb) < need) ++nb;
    ensure_base(nb);
    int sz = 1 << nb;
    vector<int> fa(sz, 0), fb(sz, 0);
    for (int i = 0; i < sz; ++i) {
      if (i < a.size()) fa[i] = a[i];
      if (i < b.size()) fb[i] = b[i];
    }
    ntt(fa, sz);
    ntt(fb, sz);
    for (int i = 0; i < sz; ++i) fa[i] = mul(fa[i], fb[i]);
    ntt(fa, sz, 1);
    vector<T> res(need);
    for (int i = 0; i < need; ++i) res[i] = fa[i];
    return res;
  }
};

int n, l, m, d;
vector<int> t, x, p;
vector<mint> sum;
NTT ntt;

mint solve();

int main() {
  cin >> n >> l;
  t.resize(n);
  for (auto &i : t) cin >> i;
  cin >> m >> d;
  x.resize(m);
  p.resize(m);
  for (int i = 0; i < m; ++i) cin >> x[i] >> p[i];
  x.push_back(l);
  cout << solve() << endl;
  return 0;
}

mint solve() {
  {  // pre
    queue<vector<int>> qu;
    for (int i = 0; i < m; ++i) {
      int len = x[i + 1] - x[i];
      vector<int> v(2 * len + 1, 0);
      mint np = mint(p[i]) / 100, revp = -np + 1;
      v[0] = v[2 * len] = (np * revp).x;
      v[len] = mint(1 - 2 * v[0]).x;
      qu.push(v);
    }
    while (qu.size() > 1) {
      auto lv = qu.front();
      qu.pop();
      qu.push(ntt.multiply(lv, qu.front()));
      qu.pop();
    }
    auto v = qu.front();
    int len = v.size();
    sum.resize(len);
    for (int i = 0; i < len; ++i) {
      sum[i] = v[i];
      if (i) sum[i] += sum[i - 1];
    }
  }
  mint res = n;
  int len = sum.size();
  for (int i = 1; i < n; ++i) {
    long long time = 1LL * (t[i] - t[0]) * l + 2LL * d * (l - x[0]);
    if (time >= 0) res -= sum[min(time / (2 * d), len - 1LL)];
  }
  return res;
}
accuracy: 1
time_ms: 310
memory_kb: 15812
final_rank: 3

code_snippet: #include <bits/stdc++.h>
using namespace std;

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};
using mint = ModInt<>;

template <int mod = 998244353>
struct NTT {
  int base, maxb, root;
  vector<int> rv, roots, invr;
  NTT() : base(1), rv({0, 1}), roots({0, 1}), invr({0, 1}) {
    assert(mod >= 3 && mod & 1);
    int tmp = mod - 1;
    maxb = 0;
    while (!(tmp & 1)) tmp >>= 1, ++maxb;
    root = 2;
    while (mpow(root, (mod - 1) >> 1) == 1) ++root;
    assert(mpow(root, mod - 1) == 1);
    root = mpow(root, (mod - 1) >> maxb);
  }

  inline int mpow(int x, int n) {
    int res = 1;
    while (n) {
      if (n & 1) res = mul(res, x);
      x = mul(x, x);
      n >>= 1;
    }
    return res;
  }

  inline int inv(int x) { return mpow(x, mod - 2); }

  inline int add(int x, int y) {
    if ((x += y) >= mod) x -= mod;
    return x;
  }

  inline int mul(int x, int y) { return (int)(1LL * x * y % mod); }

  void ensure_base(int nb) {
    if (nb <= base) return;
    rv.resize(1 << nb);
    roots.resize(1 << nb);
    invr.resize(1 << nb);
    for (int i = 0; i < (1 << nb); ++i)
      rv[i] = (rv[i >> 1] >> 1) + ((i & 1) << (nb - 1));
    assert(nb <= maxb);
    while (base < nb) {
      int z = mpow(root, 1 << (maxb - 1 - base)), invz = inv(z);
      for (int i = 1 << (base - 1); i < (1 << base); ++i) {
        roots[i << 1] = roots[i];
        roots[(i << 1) + 1] = mul(roots[i], z);
        invr[i << 1] = invr[i];
        invr[(i << 1) + 1] = mul(invr[i], invz);
      }
      ++base;
    }
  }
  void ntt(vector<int> &a, int n, bool sg = 0) {
    assert((n & (n - 1)) == 0);
    for (int i = 0; i < n; ++i)
      if (i < rv[i]) swap(a[i], a[rv[i]]);
    for (int k = 1; k < n; k <<= 1)
      for (int i = 0; i < n; i += 2 * k)
        for (int j = 0; j < k; ++j) {
          int z = mul(a[i + j + k], (sg ? roots[j + k] : invr[j + k]));
          a[i + j + k] = add(a[i + j], mod - z);
          a[i + j] = add(a[i + j], z);
        }
    int invn = inv(n);
    if (sg)
      for (int i = 0; i < n; ++i) a[i] = mul(a[i], invn);
  }
  template <class T>
  vector<T> multiply(const vector<T> &a, const vector<T> &b) {
    int need = a.size() + b.size() - 1;
    int nb = 1;
    while ((1 << nb) < need) ++nb;
    ensure_base(nb);
    int sz = 1 << nb;
    vector<int> fa(sz, 0), fb(sz, 0);
    for (int i = 0; i < sz; ++i) {
      if (i < a.size()) fa[i] = a[i];
      if (i < b.size()) fb[i] = b[i];
    }
    ntt(fa, sz);
    ntt(fb, sz);
    for (int i = 0; i < sz; ++i) fa[i] = mul(fa[i], fb[i]);
    ntt(fa, sz, 1);
    vector<T> res(need);
    for (int i = 0; i < need; ++i) res[i] = fa[i];
    mint x = 0;
    for (auto p : res) x += p;
    cout << x << endl;
    x = 0;
    for (auto p : a) x += p;
    cout << x << endl;
    x = 0;
    for (auto p : b) x += p;
    cout << x << endl;
    return res;
  }
};

template <int mod>
struct NumberTheoreticTransform {
  vector<int> rev, rts;
  int base, max_base, root;

  NumberTheoreticTransform() : base(1), rev{0, 1}, rts{0, 1} {
    assert(mod >= 3 && mod % 2 == 1);
    auto tmp = mod - 1;
    max_base = 0;
    while (tmp % 2 == 0) tmp >>= 1, max_base++;
    root = 2;
    while (mod_pow(root, (mod - 1) >> 1) == 1) ++root;
    assert(mod_pow(root, mod - 1) == 1);
    root = mod_pow(root, (mod - 1) >> max_base);
  }

  inline int mod_pow(int x, int n) {
    int ret = 1;
    while (n > 0) {
      if (n & 1) ret = mul(ret, x);
      x = mul(x, x);
      n >>= 1;
    }
    return ret;
  }

  inline int inverse(int x) { return mod_pow(x, mod - 2); }

  inline unsigned add(unsigned x, unsigned y) {
    x += y;
    if (x >= mod) x -= mod;
    return x;
  }

  inline unsigned mul(unsigned a, unsigned b) {
    return 1ull * a * b % (unsigned long long)mod;
  }

  void ensure_base(int nbase) {
    if (nbase <= base) return;
    rev.resize(1 << nbase);
    rts.resize(1 << nbase);
    for (int i = 0; i < (1 << nbase); i++) {
      rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
    }
    assert(nbase <= max_base);
    while (base < nbase) {
      int z = mod_pow(root, 1 << (max_base - 1 - base));
      for (int i = 1 << (base - 1); i < (1 << base); i++) {
        rts[i << 1] = rts[i];
        rts[(i << 1) + 1] = mul(rts[i], z);
      }
      ++base;
    }
  }

  void ntt(vector<int> &a) {
    const int n = (int)a.size();
    assert((n & (n - 1)) == 0);
    int zeros = __builtin_ctz(n);
    ensure_base(zeros);
    int shift = base - zeros;
    for (int i = 0; i < n; i++) {
      if (i < (rev[i] >> shift)) {
        swap(a[i], a[rev[i] >> shift]);
      }
    }
    for (int k = 1; k < n; k <<= 1) {
      for (int i = 0; i < n; i += 2 * k) {
        for (int j = 0; j < k; j++) {
          int z = mul(a[i + j + k], rts[j + k]);
          a[i + j + k] = add(a[i + j], mod - z);
          a[i + j] = add(a[i + j], z);
        }
      }
    }
  }

  vector<int> multiply(vector<int> a, vector<int> b) {
    int need = a.size() + b.size() - 1;
    int nbase = 1;
    while ((1 << nbase) < need) nbase++;
    ensure_base(nbase);
    int sz = 1 << nbase;
    a.resize(sz, 0);
    b.resize(sz, 0);
    ntt(a);
    ntt(b);
    int inv_sz = inverse(sz);
    for (int i = 0; i < sz; i++) {
      a[i] = mul(a[i], mul(b[i], inv_sz));
    }
    reverse(a.begin() + 1, a.end());
    ntt(a);
    a.resize(need);
    return a;
  }
};

int n, l, m, d;
vector<int> t, x, p;
vector<mint> sum;
NTT ntt;

mint solve();

int main() {
  cin >> n >> l;
  t.resize(n);
  for (auto &i : t) cin >> i;
  cin >> m >> d;
  x.resize(m);
  p.resize(m);
  for (int i = 0; i < m; ++i) cin >> x[i] >> p[i];
  x.push_back(l);
  cout << solve() << endl;
  return 0;
}

mint solve() {
  {  // pre
    queue<vector<int>> qu;
    for (int i = 0; i < m; ++i) {
      int len = x[i + 1] - x[i];
      vector<int> v(2 * len + 1, 0);
      mint np = mint(p[i]) / 100, revp = -np + 1;
      v[0] = v[2 * len] = (np * revp).x;
      v[len] = mint(1 - 2 * v[0]).x;
      qu.push(v);
    }
    NumberTheoreticTransform<998244353> ntt2;
    while (qu.size() > 1) {
      auto lv = qu.front();
      qu.pop();
      auto rv = qu.front();
      qu.pop();
      auto v = ntt2.multiply(lv, rv);
      qu.push(v);
    }
    auto v = qu.front();
    int len = v.size();
    sum.resize(len);
    for (int i = 0; i < len; ++i) {
      sum[i] = v[i];
      if (i) sum[i] += sum[i - 1];
    }
  }
  mint res = n;
  int len = sum.size();
  for (int i = 1; i < n; ++i) {
    long long time = 1LL * (t[i] - t[0]) * l + 2LL * d * (l - x[0]);
    if (time >= 0) res -= sum[min(time / (2 * d), len - 1LL)];
  }
  return res;
}
accuracy: 1
time_ms: 320
memory_kb: 14480
final_rank: 2

code_snippet: #include <bits/stdc++.h>
using namespace std;

template <int mod = (int)(998244353)>
struct ModInt {
  int x;
  constexpr ModInt() : x(0) {}
  constexpr ModInt(int64_t y)
      : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}
  constexpr ModInt &operator+=(const ModInt &p) noexcept {
    if ((x += p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator-=(const ModInt &p) noexcept {
    if ((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }
  constexpr ModInt &operator*=(const ModInt &p) noexcept {
    x = (int)(1LL * x * p.x % mod);
    return *this;
  }
  constexpr ModInt &operator/=(const ModInt &p) noexcept {
    *this *= p.inverse();
    return *this;
  }
  constexpr ModInt operator-() const { return ModInt(-x); }
  constexpr ModInt operator+(const ModInt &p) const noexcept {
    return ModInt(*this) += p;
  }
  constexpr ModInt operator-(const ModInt &p) const noexcept {
    return ModInt(*this) -= p;
  }
  constexpr ModInt operator*(const ModInt &p) const noexcept {
    return ModInt(*this) *= p;
  }
  constexpr ModInt operator/(const ModInt &p) const noexcept {
    return ModInt(*this) /= p;
  }
  constexpr bool operator==(const ModInt &p) const noexcept { return x == p.x; }
  constexpr bool operator!=(const ModInt &p) const noexcept { return x != p.x; }
  constexpr ModInt inverse() const noexcept {
    int a = x, b = mod, u = 1, v = 0, t = 0;
    while (b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }
  constexpr ModInt pow(int64_t n) const {
    ModInt res(1), mul(x);
    while (n) {
      if (n & 1) res *= mul;
      mul *= mul;
      n >>= 1;
    }
    return res;
  }
  friend constexpr ostream &operator<<(ostream &os, const ModInt &p) noexcept {
    return os << p.x;
  }
  friend constexpr istream &operator>>(istream &is, ModInt &a) noexcept {
    int64_t t = 0;
    is >> t;
    a = ModInt<mod>(t);
    return (is);
  }
  constexpr int get_mod() { return mod; }
};
using mint = ModInt<>;

template <int mod = 998244353>
struct NTT {
  int base, maxb, root;
  vector<int> rv, roots, invr;
  NTT() : base(1), rv({0, 1}), roots({0, 1}), invr({0, 1}) {
    assert(mod >= 3 && mod & 1);
    int tmp = mod - 1;
    maxb = 0;
    while (!(tmp & 1)) tmp >>= 1, ++maxb;
    root = 2;
    while (mpow(root, (mod - 1) >> 1) == 1) ++root;
    assert(mpow(root, mod - 1) == 1);
    root = mpow(root, (mod - 1) >> maxb);
  }

  inline int mpow(int x, int n) {
    int res = 1;
    while (n) {
      if (n & 1) res = mul(res, x);
      x = mul(x, x);
      n >>= 1;
    }
    return res;
  }

  inline int inv(int x) { return mpow(x, mod - 2); }

  inline int add(int x, int y) {
    if ((x += y) >= mod) x -= mod;
    return x;
  }

  inline int mul(int x, int y) { return (int)(1LL * x * y % mod); }

  void ensure_base(int nb) {
    if (nb <= base) return;
    rv.resize(1 << nb);
    roots.resize(1 << nb);
    invr.resize(1 << nb);
    for (int i = 0; i < (1 << nb); ++i)
      rv[i] = (rv[i >> 1] >> 1) + ((i & 1) << (nb - 1));
    assert(nb <= maxb);
    while (base < nb) {
      int z = mpow(root, 1 << (maxb - 1 - base)), invz = inv(z);
      for (int i = 1 << (base - 1); i < (1 << base); ++i) {
        roots[i << 1] = roots[i];
        roots[(i << 1) + 1] = mul(roots[i], z);
        invr[i << 1] = invr[i];
        invr[(i << 1) + 1] = mul(invr[i], invz);
      }
      ++base;
    }
  }
  void ntt(vector<int> &a, int n, bool sg = 0) {
    assert((n & (n - 1)) == 0);
    for (int i = 0; i < n; ++i)
      if (i < rv[i]) swap(a[i], a[rv[i]]);
    for (int k = 1; k < n; k <<= 1)
      for (int i = 0; i < n; i += 2 * k)
        for (int j = 0; j < k; ++j) {
          int z = mul(a[i + j + k], (sg ? roots[j + k] : invr[j + k]));
          a[i + j + k] = add(a[i + j], mod - z);
          a[i + j] = add(a[i + j], z);
        }
    int invn = inv(n);
    if (sg)
      for (int i = 0; i < n; ++i) a[i] = mul(a[i], invn);
  }
  template <class T>
  vector<T> multiply(const vector<T> &a, const vector<T> &b) {
    int need = a.size() + b.size() - 1;
    int nb = 1;
    while ((1 << nb) < need) ++nb;
    ensure_base(nb);
    int sz = 1 << nb;
    vector<int> fa(sz, 0), fb(sz, 0);
    for (int i = 0; i < sz; ++i) {
      if (i < a.size()) fa[i] = a[i];
      if (i < b.size()) fb[i] = b[i];
    }
    ntt(fa, sz);
    ntt(fb, sz);
    for (int i = 0; i < sz; ++i) fa[i] = mul(fa[i], fb[i]);
    ntt(fa, sz, 1);
    vector<T> res(need);
    for (int i = 0; i < need; ++i) res[i] = fa[i];
    mint x = 0;
    for (auto p : res) x += p;
    cout << x << endl;
    x = 0;
    for (auto p : a) x += p;
    cout << x << endl;
    x = 0;
    for (auto p : b) x += p;
    cout << x << endl;
    return res;
  }
};

template <int mod>
struct NumberTheoreticTransform {
  vector<int> rev, rts;
  int base, max_base, root;

  NumberTheoreticTransform() : base(1), rev{0, 1}, rts{0, 1} {
    assert(mod >= 3 && mod % 2 == 1);
    auto tmp = mod - 1;
    max_base = 0;
    while (tmp % 2 == 0) tmp >>= 1, max_base++;
    root = 2;
    while (mod_pow(root, (mod - 1) >> 1) == 1) ++root;
    assert(mod_pow(root, mod - 1) == 1);
    root = mod_pow(root, (mod - 1) >> max_base);
  }

  inline int mod_pow(int x, int n) {
    int ret = 1;
    while (n > 0) {
      if (n & 1) ret = mul(ret, x);
      x = mul(x, x);
      n >>= 1;
    }
    return ret;
  }

  inline int inverse(int x) { return mod_pow(x, mod - 2); }

  inline unsigned add(unsigned x, unsigned y) {
    x += y;
    if (x >= mod) x -= mod;
    return x;
  }

  inline unsigned mul(unsigned a, unsigned b) {
    return 1ull * a * b % (unsigned long long)mod;
  }

  void ensure_base(int nbase) {
    if (nbase <= base) return;
    rev.resize(1 << nbase);
    rts.resize(1 << nbase);
    for (int i = 0; i < (1 << nbase); i++) {
      rev[i] = (rev[i >> 1] >> 1) + ((i & 1) << (nbase - 1));
    }
    assert(nbase <= max_base);
    while (base < nbase) {
      int z = mod_pow(root, 1 << (max_base - 1 - base));
      for (int i = 1 << (base - 1); i < (1 << base); i++) {
        rts[i << 1] = rts[i];
        rts[(i << 1) + 1] = mul(rts[i], z);
      }
      ++base;
    }
  }

  void ntt(vector<int> &a) {
    const int n = (int)a.size();
    assert((n & (n - 1)) == 0);
    int zeros = __builtin_ctz(n);
    ensure_base(zeros);
    int shift = base - zeros;
    for (int i = 0; i < n; i++) {
      if (i < (rev[i] >> shift)) {
        swap(a[i], a[rev[i] >> shift]);
      }
    }
    for (int k = 1; k < n; k <<= 1) {
      for (int i = 0; i < n; i += 2 * k) {
        for (int j = 0; j < k; j++) {
          int z = mul(a[i + j + k], rts[j + k]);
          a[i + j + k] = add(a[i + j], mod - z);
          a[i + j] = add(a[i + j], z);
        }
      }
    }
  }

  vector<int> multiply(vector<int> a, vector<int> b) {
    int need = a.size() + b.size() - 1;
    int nbase = 1;
    while ((1 << nbase) < need) nbase++;
    ensure_base(nbase);
    int sz = 1 << nbase;
    a.resize(sz, 0);
    b.resize(sz, 0);
    ntt(a);
    ntt(b);
    int inv_sz = inverse(sz);
    for (int i = 0; i < sz; i++) {
      a[i] = mul(a[i], mul(b[i], inv_sz));
    }
    reverse(a.begin() + 1, a.end());
    ntt(a);
    a.resize(need);
    return a;
  }
};

int n, l, m, d;
vector<int> t, x, p;
vector<mint> sum;
NTT ntt;

mint solve();

int main() {
  cin >> n >> l;
  t.resize(n);
  for (auto &i : t) cin >> i;
  cin >> m >> d;
  x.resize(m);
  p.resize(m);
  for (int i = 0; i < m; ++i) cin >> x[i] >> p[i];
  x.push_back(l);
  cout << solve() << endl;
  return 0;
}

mint solve() {
  {  // pre
    queue<vector<int>> qu;
    for (int i = 0; i < m; ++i) {
      int len = x[i + 1] - x[i];
      vector<int> v(2 * len + 1, 0);
      mint np = mint(p[i]) / 100, revp = -np + 1;
      v[0] = v[2 * len] = (np * revp).x;
      v[len] = mint(1 - 2 * v[0]).x;
      qu.push(v);
    }
    NumberTheoreticTransform<998244353> ntt2;
    while (qu.size() > 1) {
      auto lv = qu.front();
      qu.pop();
      auto rv = qu.front();
      qu.pop();
      auto v = ntt2.multiply(lv, rv);
      qu.push(v);
    }
    auto v = qu.front();
    int len = v.size();
    sum.resize(len);
    for (int i = 0; i < len; ++i) {
      sum[i] = v[i];
      if (i) sum[i] += sum[i - 1];
    }
  }
  mint res = n;
  for (int i = 1; i < n; ++i) {
    long long time = 1LL * (t[i] - t[0]) * l + 2LL * d * (l - x[0]);
    if (time >= 0) res -= sum[time / (2 * d)];
  }
  return res;
}
accuracy: 0.075
time_ms: 320
memory_kb: 13560
final_rank: 16

code_snippet: //#define _GLIBCXX_DEBUG

#include<bits/stdc++.h>
using namespace std;

#define endl '\n'
#define lfs cout<<fixed<<setprecision(10)
#define ALL(a)  (a).begin(),(a).end()
#define ALLR(a)  (a).rbegin(),(a).rend()
#define spa << " " <<
#define fi first
#define se second
#define MP make_pair
#define MT make_tuple
#define PB push_back
#define EB emplace_back
#define rep(i,n,m) for(ll i = (n); i < (ll)(m); i++)
#define rrep(i,n,m) for(ll i = (ll)(m) - 1; i >= (ll)(n); i--)
using ll = long long;
using ld = long double;
const ll MOD1 = 1e9+7;
const ll MOD9 = 998244353;
const ll INF = 1e18;
using P = pair<ll, ll>;
template<typename T1, typename T2>bool chmin(T1 &a,T2 b){if(a>b){a=b;return true;}else return false;}
template<typename T1, typename T2>bool chmax(T1 &a,T2 b){if(a<b){a=b;return true;}else return false;}
ll median(ll a,ll b, ll c){return a+b+c-max({a,b,c})-min({a,b,c});}
void ans1(bool x){if(x) cout<<"Yes"<<endl;else cout<<"No"<<endl;}
void ans2(bool x){if(x) cout<<"YES"<<endl;else cout<<"NO"<<endl;}
void ans3(bool x){if(x) cout<<"Yay!"<<endl;else cout<<":("<<endl;}
template<typename T1,typename T2>void ans(bool x,T1 y,T2 z){if(x)cout<<y<<endl;else cout<<z<<endl;}  
template<typename T>void debug(vector<vector<T>>&v,ll h,ll w){for(ll i=0;i<h;i++){cout<<v[i][0];for(ll j=1;j<w;j++)cout spa v[i][j];cout<<endl;}};
void debug(vector<string>&v,ll h,ll w){for(ll i=0;i<h;i++){for(ll j=0;j<w;j++)cout<<v[i][j];cout<<endl;}};
template<typename T>void debug(vector<T>&v,ll n){if(n!=0)cout<<v[0];for(ll i=1;i<n;i++)cout spa v[i];cout<<endl;};
template<typename T>vector<vector<T>>vec(ll x, ll y, T w){vector<vector<T>>v(x,vector<T>(y,w));return v;}
ll gcd(ll x,ll y){ll r;while(y!=0&&(r=x%y)!=0){x=y;y=r;}return y==0?x:y;}
vector<ll>dx={1,-1,0,0,1,1,-1,-1};vector<ll>dy={0,0,1,-1,1,-1,1,-1};
template<typename T>vector<T> make_v(size_t a,T b){return vector<T>(a,b);}
template<typename... Ts>auto make_v(size_t a,Ts... ts){return vector<decltype(make_v(ts...))>(a,make_v(ts...));}
template<typename T1, typename T2>ostream &operator<<(ostream &os, const pair<T1, T2>&p){return os << p.first << " " << p.second;}
template<typename T>ostream &operator<<(ostream &os, const vector<T> &v){for(auto &z:v)os << z << " ";cout<<"|"; return os;}
//mt19937 mt(chrono::steady_clock::now().time_since_epoch().count());
template< int mod >
struct ModInt {
  int x;

  ModInt() : x(0) {}

  ModInt(int64_t y) : x(y >= 0 ? y % mod : (mod - (-y) % mod) % mod) {}

  ModInt &operator+=(const ModInt &p) {
    if((x += p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator-=(const ModInt &p) {
    if((x += mod - p.x) >= mod) x -= mod;
    return *this;
  }

  ModInt &operator*=(const ModInt &p) {
    x = (int) (1LL * x * p.x % mod);
    return *this;
  }

  ModInt &operator/=(const ModInt &p) {
    *this *= p.inverse();
    return *this;
  }

  ModInt operator-() const { return ModInt(-x); }

  friend ModInt operator+(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) += rhs;
  }
  friend ModInt operator-(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) -= rhs;
  }
  friend ModInt operator*(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) *= rhs;
  }
  friend ModInt operator/(const ModInt& lhs, const ModInt& rhs) {
        return ModInt(lhs) /= rhs;
  }

  bool operator==(const ModInt &p) const { return x == p.x; }

  bool operator!=(const ModInt &p) const { return x != p.x; }

  ModInt inverse() const {
    int a = x, b = mod, u = 1, v = 0, t;
    while(b > 0) {
      t = a / b;
      swap(a -= t * b, b);
      swap(u -= t * v, v);
    }
    return ModInt(u);
  }

  ModInt pow(int64_t n) const {
    ModInt ret(1), mul(x);
    while(n > 0) {
      if(n & 1) ret *= mul;
      mul *= mul;
      n >>= 1;
    }
    return ret;
  }

  friend ostream &operator<<(ostream &os, const ModInt &p) {
    return os << p.x;
  }

  friend istream &operator>>(istream &is, ModInt &a) {
    int64_t t;
    is >> t;
    a = ModInt< mod >(t);
    return (is);
  }

  static int get_mod() { return mod; }
};
using modint = ModInt< MOD9 >;modint pow(ll n, ll x){return modint(n).pow(x);}modint pow(modint n, ll x){return n.pow(x);}
//using modint=ld;
template< typename Mint >
struct NumberTheoreticTransformFriendlyModInt {

  vector< Mint > dw, idw;
  int max_base;
  Mint root;

  NumberTheoreticTransformFriendlyModInt() {
    const unsigned mod = Mint::get_mod();
    assert(mod >= 3 && mod % 2 == 1);
    auto tmp = mod - 1;
    max_base = 0;
    while(tmp % 2 == 0) tmp >>= 1, max_base++;
    root = 2;
    while(root.pow((mod - 1) >> 1) == 1) root += 1;
    assert(root.pow(mod - 1) == 1);
    dw.resize(max_base);
    idw.resize(max_base);
    for(int i = 0; i < max_base; i++) {
      dw[i] = -root.pow((mod - 1) >> (i + 2));
      idw[i] = Mint(1) / dw[i];
    }
  }

  void ntt(vector< Mint > &a) {
    const int n = (int) a.size();
    assert((n & (n - 1)) == 0);
    assert(__builtin_ctz(n) <= max_base);
    for(int m = n; m >>= 1;) {
      Mint w = 1;
      for(int s = 0, k = 0; s < n; s += 2 * m) {
        for(int i = s, j = s + m; i < s + m; ++i, ++j) {
          auto x = a[i], y = a[j] * w;
          a[i] = x + y, a[j] = x - y;
        }
        w *= dw[__builtin_ctz(++k)];
      }
    }
  }

  void intt(vector< Mint > &a, bool f = true) {
    const int n = (int) a.size();
    assert((n & (n - 1)) == 0);
    assert(__builtin_ctz(n) <= max_base);
    for(int m = 1; m < n; m *= 2) {
      Mint w = 1;
      for(int s = 0, k = 0; s < n; s += 2 * m) {
        for(int i = s, j = s + m; i < s + m; ++i, ++j) {
          auto x = a[i], y = a[j];
          a[i] = x + y, a[j] = (x - y) * w;
        }
        w *= idw[__builtin_ctz(++k)];
      }
    }
    if(f) {
      Mint inv_sz = Mint(1) / n;
      for(int i = 0; i < n; i++) a[i] *= inv_sz;
    }
  }

  vector< Mint > multiply(vector< Mint > a, vector< Mint > b) {
    int need = a.size() + b.size() - 1;
    int nbase = 1;
    while((1 << nbase) < need) nbase++;
    int sz = 1 << nbase;
    a.resize(sz, 0);
    b.resize(sz, 0);
    ntt(a);
    ntt(b);
    Mint inv_sz = Mint(1) / sz;
    for(int i = 0; i < sz; i++) a[i] *= b[i] * inv_sz;
    intt(a, false);
    a.resize(need);
    return a;
  }
};
int main(){
  cin.tie(nullptr);
  ios_base::sync_with_stdio(false);
  ll res=0,buf=0;
  bool judge = true;
  ll n,l;cin>>n>>l;
  vector<ll>t(n);
  rep(i,0,n)cin>>t[i];
  ll m,d;cin>>m>>d;
  vector<ll>x(m),p(m);
  rep(i,0,m)cin>>x[i]>>p[i];
  x.PB(l);
  vector<vector<modint>>f(m);
  ll geta=0;
  queue<ll>que;
  rep(i,0,m){
    modint prob=(modint)p[i]/100;
    ll sz=x[i+1]-x[i];
    f[i].assign(4*sz+1,0);
    geta+=2*sz;
    f[i][0]=(1-prob)*prob;
    f[i][2*sz]=prob*prob+(1-prob)*(1-prob);
    f[i][4*sz]=(1-prob)*prob;
    que.push(i);
  }
  NumberTheoreticTransformFriendlyModInt<modint>ntt;
  while(que.size()>=2){
    auto l=que.front();que.pop();
    auto r=que.front();que.pop();
    f[l]=ntt.multiply(f[l],f[r]);
    //debug(f[l],f[l].size());
    que.push(l);
  }
  ll r=que.front();
  vector<modint>fb(f[r].size()+1);
  rep(i,0,f[r].size())fb[i+1]=fb[i]+f[r][i];
  ll sz=f[r].size();
  //cout<<f[r][0]*4<<endl;
  //cout<<f<<endl;
  //debug(fb,sz+1);
  //debug(f[r],sz);
  modint ret=1;
  rep(i,1,n){
    ll dif=(t[0]-t[i])*l;
    if(dif>0)dif=(dif+d-1)/d;
    else dif/=d;
    //cout<<dif spa geta spa clamp(dif+geta,0LL,sz)<<endl;
    ret+=fb[clamp(dif+geta,0LL,sz)];
  }
  cout<<ret<<endl;
  return 0;
}
accuracy: 1
time_ms: 550
memory_kb: 65356
final_rank: 11

code_snippet: #include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <stack>
#include <functional>
#include <bitset>
#include <assert.h>
#include <unordered_map>
#include <fstream>
#include <ctime>
#include <complex>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = 1<<30;
const ll linf = 1LL<<62;
const int MAX = 2020000;
ll dy[8] = {1,-1,0,0,1,-1,1,-1};
ll dx[8] = {0,0,1,-1,1,-1,-1,1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << "debug: " << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << "debug: " << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//const int mod = 1e9 + 7;
const int mod = 998244353;

#define MOD 998244353
#define root 3
 
unsigned int add(const unsigned int x, const unsigned int y)
{
    return (x + y < MOD) ? x + y : x + y - MOD;
}
 
unsigned int sub(const unsigned int x, const unsigned int y)
{
    return (x >= y) ? (x - y) : (MOD - y + x);
}
 
unsigned int mul(const unsigned int x, const unsigned int y)
{
    return (unsigned long long)x * y % MOD;
}
 
unsigned int mod_pow(unsigned int x, unsigned int n)
{
    unsigned int res = 1;
    while(n > 0){
        if(n & 1){ res = mul(res, x); }
        x = mul(x, x);
        n >>= 1;
    }
    return res;
}
 
unsigned int inverse(const unsigned int x)
{
    return mod_pow(x, MOD - 2);
}
 
void ntt(vector<int>& a, const bool rev = false)
{
    unsigned int i, j, k, l, p, q, r, s;
    const unsigned int size = a.size();
    if(size == 1) return;
    vector<int> b(size);
    r = rev ? (MOD - 1 - (MOD - 1) / size) : (MOD - 1) / size;
    s = mod_pow(root, r);
    vector<unsigned int> kp(size / 2 + 1, 1);
    for(i = 0; i < size / 2; ++i) kp[i + 1] = mul(kp[i], s);
    for(i = 1, l = size / 2; i < size; i <<= 1, l >>= 1){
        for(j = 0, r = 0; j < l; ++j, r += i){
            for(k = 0, s = kp[i * j]; k < i; ++k){
                p = a[k + r], q = a[k + r + size / 2];
                b[k + 2 * r] = add(p, q);
                b[k + 2 * r + i] = mul(sub(p, q), s);
            }
        }
        swap(a, b);
    }
    if(rev){
        s = inverse(size);
        for(i = 0; i < size; i++){ a[i] = mul(a[i], s); }
    }
}
 
vector<int> convolute(const vector<int>& a, const vector<int>& b)
{
    const int size = (int)a.size() + (int)b.size() - 1;
    int t = 1;
    while(t < size){ t <<= 1; }
    vector<int> A(t, 0), B(t, 0);
    for(int i = 0; i < (int)a.size(); i++){ A[i] = a[i]; }
    for(int i = 0; i < (int)b.size(); i++){ B[i] = b[i]; }
    ntt(A), ntt(B);
    for (int i = 0; i < t; i++){ A[i] = mul(A[i], B[i]); }
    ntt(A, true);
    A.resize(size);
    return A;
}

ll modpow(ll x, ll n, ll mod){
	ll res = 1;
	while(n > 0){
		if(n & 1) res = res * x % mod;
		x = x * x % mod;
		n >>= 1;
	}
	return res;
}

int main(){
	ll n,L; cin >> n >> L;
	vector<int> t(n); rep(i,n) cin >> t[i];
	int m,d; cin >> m >> d;
	vector<int> x(m+1),p(m);
	rep(i,m) cin >> x[i] >> p[i];
	x[m] = L;
	vector<vector<int>> v;
	int id = 0;
	priority_queue<P,vector<P>,greater<P>> pq;
	int inv = modpow(100,mod-2,mod);
	rep(i,m){
		ll dist = x[i+1] - x[i];
		vector<int> vec(dist+1,0);
		pq.emplace(dist+1,id);
		vec[0] = (ll)p[i] * inv % mod;
		vec[dist] = (1 - (ll)p[i] * inv % mod + mod) % mod;
		v.push_back(vec);
		id++;
	}
	while(pq.size() > 1){
		int w = pq.top().second; pq.pop();
		int y = pq.top().second; pq.pop();
		v[y] = convolute(v[w], v[y]);
		pq.emplace(v[y].size(), y);
	}
	int z = pq.top().second;
	auto b = v[z];
	reverse(all(b));
	auto c = convolute(v[z], b);
	vector<int> acc(2*L+1, 0);
	rep(i,c.size()) acc[i+1] = (acc[i] + c[i]) % mod;
	for(int i=c.size(); i<2*L; i++) acc[i+1] = acc[i];
	ll ans = 1;
	REP(i,1,n){
		ll lim;
		if(t[0] > t[i]){
			lim = (L * (t[0] - t[i]) + 2*d - 1) / (2*d);
		}else{
			lim = (L * (t[0] - t[i])) / (2*d);
		}
		ans += acc[min(2*L,max(0LL,lim+L-x[0]))];
	}
	ans %= mod;
	cout << ans << "\n";
}
accuracy: 1
time_ms: 440
memory_kb: 27452
final_rank: 9

code_snippet: #include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <stack>
#include <functional>
#include <bitset>
#include <assert.h>
#include <unordered_map>
#include <fstream>
#include <ctime>
#include <complex>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = 1<<30;
const ll linf = 1LL<<62;
const int MAX = 2020000;
ll dy[8] = {1,-1,0,0,1,-1,1,-1};
ll dx[8] = {0,0,1,-1,1,-1,-1,1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << "debug: " << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << "debug: " << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//const int mod = 1e9 + 7;
const int mod = 998244353;

#define MOD 998244353
#define root 3
 
unsigned int add(const unsigned int x, const unsigned int y)
{
    return (x + y < MOD) ? x + y : x + y - MOD;
}
 
unsigned int sub(const unsigned int x, const unsigned int y)
{
    return (x >= y) ? (x - y) : (MOD - y + x);
}
 
unsigned int mul(const unsigned int x, const unsigned int y)
{
    return (unsigned long long)x * y % MOD;
}
 
unsigned int mod_pow(unsigned int x, unsigned int n)
{
    unsigned int res = 1;
    while(n > 0){
        if(n & 1){ res = mul(res, x); }
        x = mul(x, x);
        n >>= 1;
    }
    return res;
}
 
unsigned int inverse(const unsigned int x)
{
    return mod_pow(x, MOD - 2);
}
 
void ntt(vector<int>& a, const bool rev = false)
{
    unsigned int i, j, k, l, p, q, r, s;
    const unsigned int size = a.size();
    if(size == 1) return;
    vector<int> b(size);
    r = rev ? (MOD - 1 - (MOD - 1) / size) : (MOD - 1) / size;
    s = mod_pow(root, r);
    vector<unsigned int> kp(size / 2 + 1, 1);
    for(i = 0; i < size / 2; ++i) kp[i + 1] = mul(kp[i], s);
    for(i = 1, l = size / 2; i < size; i <<= 1, l >>= 1){
        for(j = 0, r = 0; j < l; ++j, r += i){
            for(k = 0, s = kp[i * j]; k < i; ++k){
                p = a[k + r], q = a[k + r + size / 2];
                b[k + 2 * r] = add(p, q);
                b[k + 2 * r + i] = mul(sub(p, q), s);
            }
        }
        swap(a, b);
    }
    if(rev){
        s = inverse(size);
        for(i = 0; i < size; i++){ a[i] = mul(a[i], s); }
    }
}
 
vector<int> convolute(const vector<int>& a, const vector<int>& b)
{
    const int size = (int)a.size() + (int)b.size() - 1;
    int t = 1;
    while(t < size){ t <<= 1; }
    vector<int> A(t, 0), B(t, 0);
    for(int i = 0; i < (int)a.size(); i++){ A[i] = a[i]; }
    for(int i = 0; i < (int)b.size(); i++){ B[i] = b[i]; }
    ntt(A), ntt(B);
    for (int i = 0; i < t; i++){ A[i] = mul(A[i], B[i]); }
    ntt(A, true);
    A.resize(size);
    return A;
}

ll modpow(ll x, ll n, ll mod){
	ll res = 1;
	while(n > 0){
		if(n & 1) res = res * x % mod;
		x = x * x % mod;
		n >>= 1;
	}
	return res;
}

int main(){
	int n,L; cin >> n >> L;
	vector<int> t(n); rep(i,n) cin >> t[i];
	int m,d; cin >> m >> d;
	vector<int> x(m+1),p(m);
	rep(i,m) cin >> x[i] >> p[i];
	x[m] = L;
	vector<vector<int>> v;
	int id = 0;
	priority_queue<P,vector<P>,greater<P>> pq;
	int inv = modpow(100,mod-2,mod);
	rep(i,m){
		ll dist = x[i+1] - x[i];
		vector<int> vec(dist+1,0);
		pq.emplace(dist+1,id);
		vec[0] = (ll)p[i] * inv % mod;
		vec[dist] = (1 - (ll)p[i] * inv % mod + mod) % mod;
		v.push_back(vec);
		id++;
	}
	while(pq.size() > 1){
		int w = pq.top().second; pq.pop();
		int y = pq.top().second; pq.pop();
		v[y] = convolute(v[w], v[y]);
		pq.emplace(v[y].size(), y);
	}
	int z = pq.top().second;
	auto b = v[z];
	reverse(all(b));
	auto c = convolute(v[z], b);
	vector<int> acc(2*L+1, 0);
	rep(i,c.size()) acc[i+1] = (acc[i] + c[i]) % mod;
	for(int i=c.size(); i<2*L; i++) acc[i+1] = acc[i];
	ll ans = 1;
	REP(i,1,n){
		int lim;
		if(t[0] > t[i]){
			lim = ((ll)L * (t[0] - t[i]) + 2*d - 1) / (2*d);
		}else{
			lim = ((ll)L * (t[0] - t[i])) / (2*d);
		}
		ans += (mod + acc[min(2*L,max(0,lim+L-x[0]))]) % mod;
		ans %= mod;
	}
	cout << ans << "\n";
}
accuracy: 0.6
time_ms: 400
memory_kb: 27444
final_rank: 14

code_snippet: #include <iostream>
#include <string>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <unordered_map>
#include <map>
#include <set>
#include <algorithm>
#include <queue>
#include <stack>
#include <functional>
#include <bitset>
#include <assert.h>
#include <unordered_map>
#include <fstream>
#include <ctime>
#include <complex>
using namespace std;
typedef long long ll;
typedef vector<ll> vl;
typedef vector<vl> vvl;
typedef vector<char> vc;
typedef vector<string> vs;
typedef vector<bool> vb;
typedef vector<double> vd;
typedef pair<ll,ll> P;
typedef pair<int,int> pii;
typedef vector<P> vpl;
typedef tuple<ll,ll,ll> tapu;
#define rep(i,n) for(int i=0; i<(n); i++)
#define REP(i,a,b) for(int i=(a); i<(b); i++)
#define all(x) (x).begin(), (x).end()
#define rall(x) (x).rbegin(), (x).rend()
const int inf = 1<<30;
const ll linf = 1LL<<62;
const int MAX = 2020000;
ll dy[8] = {1,-1,0,0,1,-1,1,-1};
ll dx[8] = {0,0,1,-1,1,-1,-1,1};
const double pi = acos(-1);
const double eps = 1e-7;
template<typename T1,typename T2> inline bool chmin(T1 &a,T2 b){
	if(a>b){
		a = b; return true;
	}
	else return false;
}
template<typename T1,typename T2> inline bool chmax(T1 &a,T2 b){
	if(a<b){
		a = b; return true;
	}
	else return false;
}
template<typename T> inline void print(T &a){
    for(auto itr = a.begin(); itr != a.end(); itr++){
		cout << *itr << " ";
	}
    cout << "\n";
}
template<typename T1,typename T2> inline void print2(T1 a, T2 b){
	cout << "debug: " << a << " " << b << "\n";
}
template<typename T1,typename T2,typename T3> inline void print3(T1 a, T2 b, T3 c){
	cout << "debug: " << a << " " << b << " " << c << "\n";
}
void mark() {cout << "#" << "\n";}
ll pcount(ll x) {return __builtin_popcountll(x);}
//const int mod = 1e9 + 7;
const int mod = 998244353;

#define MOD 998244353
#define root 3
 
unsigned int add(const unsigned int x, const unsigned int y)
{
    return (x + y < MOD) ? x + y : x + y - MOD;
}
 
unsigned int sub(const unsigned int x, const unsigned int y)
{
    return (x >= y) ? (x - y) : (MOD - y + x);
}
 
unsigned int mul(const unsigned int x, const unsigned int y)
{
    return (unsigned long long)x * y % MOD;
}
 
unsigned int mod_pow(unsigned int x, unsigned int n)
{
    unsigned int res = 1;
    while(n > 0){
        if(n & 1){ res = mul(res, x); }
        x = mul(x, x);
        n >>= 1;
    }
    return res;
}
 
unsigned int inverse(const unsigned int x)
{
    return mod_pow(x, MOD - 2);
}
 
void ntt(vector<int>& a, const bool rev = false)
{
    unsigned int i, j, k, l, p, q, r, s;
    const unsigned int size = a.size();
    if(size == 1) return;
    vector<int> b(size);
    r = rev ? (MOD - 1 - (MOD - 1) / size) : (MOD - 1) / size;
    s = mod_pow(root, r);
    vector<unsigned int> kp(size / 2 + 1, 1);
    for(i = 0; i < size / 2; ++i) kp[i + 1] = mul(kp[i], s);
    for(i = 1, l = size / 2; i < size; i <<= 1, l >>= 1){
        for(j = 0, r = 0; j < l; ++j, r += i){
            for(k = 0, s = kp[i * j]; k < i; ++k){
                p = a[k + r], q = a[k + r + size / 2];
                b[k + 2 * r] = add(p, q);
                b[k + 2 * r + i] = mul(sub(p, q), s);
            }
        }
        swap(a, b);
    }
    if(rev){
        s = inverse(size);
        for(i = 0; i < size; i++){ a[i] = mul(a[i], s); }
    }
}
 
vector<int> convolute(const vector<int>& a, const vector<int>& b)
{
    const int size = (int)a.size() + (int)b.size() - 1;
    int t = 1;
    while(t < size){ t <<= 1; }
    vector<int> A(t, 0), B(t, 0);
    for(int i = 0; i < (int)a.size(); i++){ A[i] = a[i]; }
    for(int i = 0; i < (int)b.size(); i++){ B[i] = b[i]; }
    ntt(A), ntt(B);
    for (int i = 0; i < t; i++){ A[i] = mul(A[i], B[i]); }
    ntt(A, true);
    A.resize(size);
    return A;
}

ll modpow(ll x, ll n, ll mod){
	ll res = 1;
	while(n > 0){
		if(n & 1) res = res * x % mod;
		x = x * x % mod;
		n >>= 1;
	}
	return res;
}

int main(){
	int n,L; cin >> n >> L;
	vector<int> t(n); rep(i,n) cin >> t[i];
	int m,d; cin >> m >> d;
	vector<int> x(m+1),p(m);
	rep(i,m) cin >> x[i] >> p[i];
	x[m] = L;
	vector<vector<int>> v;
	int id = 0;
	priority_queue<P,vector<P>,greater<P>> pq;
	int inv = modpow(100,mod-2,mod);
	rep(i,m){
		ll dist = x[i+1] - x[i];
		vector<int> vec(dist+1,0);
		pq.emplace(dist+1,id);
		vec[0] = (ll)p[i] * inv % mod;
		vec[dist] = (1 - (ll)p[i] * inv % mod + mod) % mod;
		v.push_back(vec);
		id++;
	}
	while(pq.size() > 1){
		int w = pq.top().second; pq.pop();
		int y = pq.top().second; pq.pop();
		v[y] = convolute(v[w], v[y]);
		pq.emplace(v[y].size(), y);
	}
	int z = pq.top().second;
	auto b = v[z];
	reverse(all(b));
	auto c = convolute(v[z], b);
	vector<int> acc(2*L+1, 0);
	rep(i,c.size()) acc[i+1] = (acc[i] + c[i]) % mod;
	for(int i=c.size(); i<2*L; i++) acc[i+1] = acc[i];
	ll ans = 1;
	REP(i,1,n){
		int lim;
		if(t[0] > t[i]){
			lim = (L * (t[0] - t[i]) + 2*d - 1) / (2*d);
		}else{
			lim = (L * (t[0] - t[i])) / (2*d);
		}
		ans += (mod + acc[min(2*L,max(0,lim+L-x[0]))]) % mod;
		ans %= mod;
	}
	cout << ans << "\n";
}
accuracy: 0.125
time_ms: 400
memory_kb: 27360
final_rank: 15

code_snippet: #include <bits/stdc++.h>
//#include <chrono>
//#pragma GCC optimize("Ofast")
using namespace std;
#define reps(i,s,n) for(int i = s; i < n; i++)
#define rep(i,n) reps(i,0,n)
#define Rreps(i,n,e) for(int i = n - 1; i >= e; --i)
#define Rrep(i,n) Rreps(i,n,0)
#define ALL(a) a.begin(), a.end()
#define fi first
#define se second

using ll = long long;
using vec = vector<ll>;
using mat = vector<vec>;

ll N,M,H,W,Q,K,A,B;
string S;
typedef pair<ll, ll> P;
const ll INF = (1LL<<58);

template<class T> bool chmin(T &a, const T &b){
    if(a > b) {a = b; return true;}
    else return false;
}
template<class T> bool chmax(T &a, const T &b){
    if(a < b) {a = b; return true;}
    else return false;
}

template <unsigned long long mod > class modint{
public:
    ll x;
    constexpr modint(){x = 0;}
    constexpr modint(ll _x) : x((_x < 0 ? ((_x += (LLONG_MAX / mod) * mod) < 0 ? _x + (LLONG_MAX / mod) * mod : _x) : _x)%mod){}
    constexpr void set_raw(ll _x){
        //_x in [0, mod)
        x = _x;
    }
    constexpr modint operator-(){
        return x == 0 ? 0 : mod - x;
    }
    constexpr modint& operator+=(const modint& a){
        if((x += a.x) >= mod) x -= mod;
        return *this;
    }
    constexpr modint operator+(const modint& a) const{
        return modint(*this) += a;
    }
    constexpr modint& operator-=(const modint& a){
        if((x -= a.x) < 0) x += mod;
        return *this;
    }
    constexpr modint operator-(const modint& a) const{
        return modint(*this) -= a;
    }
    constexpr modint& operator*=(const modint& a){
        (x *= a.x)%=mod;
        return *this;
    }
    constexpr modint operator*(const modint& a) const{
        return modint(*this) *= a;
    }
    constexpr modint pow(unsigned long long pw) const{
        modint res(1), comp(*this);
        while(pw){
            if(pw&1) res *= comp;
            comp *= comp;
            pw >>= 1;
        }
        return res;
    }
    //以下、modが素数のときのみ
    constexpr modint inv() const{
        return modint(*this).pow(mod - 2);
    }
    constexpr modint& operator/=(const modint &a){
        (x *= a.inv().x)%=mod;
        return *this;
    }
    constexpr modint operator/(const modint &a) const{
        return modint(*this) /= a;
    }
};
#define mod1 998244353
using mint = modint<mod1>;

ostream& operator<<(ostream& os, const mint& a){
    os << a.x;
    return os;
}
using vm = vector<mint>;
class NTT{
    const int root;

    void make_root_pow(int n, vm &root_pow){
        root_pow.resize(n + 1);
        mint new_root = mint(root).pow((mod1 - 1) / n);
        root_pow[0].x = 1;
        rep(i,n){
            root_pow[i + 1] = root_pow[i] * new_root;
        }
    }
    static void make_bit_reverse(int n, vector<int> &v){
        v.resize(n);
        iota(ALL(v), 0);
        for(int i = 1; (1<<i) <= n; ++i){
            int l = 1<<(i - 1), r = 1<<i;
            int plus = n >> i;
            for(int j = l; j < r; ++j){
                int temp = v[j - l] + plus;
                if(j < temp) swap(v[j], v[temp]);
            }
        }
    }
    static void dft(int n, vm &f, bool inv, vm &root_pow, vector<int> &id){
        vm g(n);
        rep(i,n) g[i] = f[id[i]];
        swap(f, g);
        for(int l = n / 2, len = 1; l >= 1; l /= 2, len *= 2){
            for(int i = 0; i < n; i += len * 2){
                rep(j, len){
                    mint z_f = (inv ? root_pow[n - l * j] : root_pow[l * j]) * f[i + len + j];
                    g[i + j] = f[i + j] + z_f;
                    g[i + len + j] = f[i + j] - z_f;
                }
            }
            swap(f, g);
        }
        if(inv) {
            mint n_inv = mint(n).inv();
            rep(i, n) f[i] *= n_inv;
        }
    }
public:
    NTT(int _x = 3) : root(_x){}
    vm convolution(vm &a, vm &b, int size_a = INT_MAX, int size_b = INT_MAX){
        chmin(size_a, (int)a.size());
        chmin(size_b, (int)b.size());
        int sz = size_a + size_b - 1, n = 1;
        while(sz > n) n *= 2;
        vm g(n), h(n), root_pow, gh(n);
        vector<int> id;
        copy(a.begin(), a.begin() + size_a, g.begin());
        copy(b.begin(), b.begin() + size_b, h.begin());
        make_root_pow(n, root_pow);
        make_bit_reverse(n, id);
        dft(n, g, false, root_pow, id);
        dft(n, h, false, root_pow, id);
        rep(i, n) gh[i] = g[i] * h[i];
        dft(n, gh, true, root_pow, id);
        gh.resize(sz);
        return gh;
    }
};

vm polynomial_product(vector<vm> &polys){
    //time complexity : O(N log^2 N) (N : sum of polys[i].size())
    struct _cmp{
        int sz;
        vm a;
        _cmp(int _sz, vm _a) : sz(_sz), a(_a){}
        bool operator > (const _cmp &b){ return sz > b.sz;}
    };
    priority_queue<_cmp, vector<_cmp>, greater<> > pque;
    for(vm &a : polys) pque.emplace((int)a.size(), a);
    NTT ntt;
    while(pque.size() > 1){
        _cmp c = pque.top(); pque.pop();
        _cmp d = pque.top(); pque.pop();
        vm res = ntt.convolution(c.a, d.a);
        pque.emplace(res.size(), res);
    }
    return pque.top().a;
}

int main() {
    ll L, D;
    cin>>N>>L;
    vec t(N);
    rep(i, N) cin>>t[i];
    cin>>M>>D;
    vec x(M), p(M);
    rep(i, M) cin>>x[i]>>p[i];
    x.push_back(L);
    vector<vm> polys(0);
    rep(i, M){
        int d = x[i+1] - x[i];
        vm temp(d + 1);
        temp[d] = mint(p[i]) / 100;
        temp[0] = mint(1) - temp[d];
        polys.push_back(temp);
    }
    vm plus = polynomial_product(polys), plus_rev(plus);
    reverse(ALL(plus_rev));
    NTT ntt;
    vm diff = ntt.convolution(plus, plus_rev);
    ll n = (L - x[0]) * 2;
    rep(i, n) diff[i + 1] += diff[i];
    if(diff[n].x != 1) cout<<diff[n]<<endl;
    mint res(N);
    reps(i, 1, N){
        ll base_adv = L * (t[i] - t[0]);
        if(n * D <= base_adv) res -= 1;
        else if(base_adv >= - n * D) res -= diff[(base_adv + n * D) / (D * 2)];
    }
    cout<<res<<endl;
}
accuracy: 1
time_ms: 350
memory_kb: 23548
final_rank: 6

code_snippet: #include <bits/stdc++.h>
//#include <chrono>
//#pragma GCC optimize("Ofast")
using namespace std;
#define reps(i,s,n) for(int i = s; i < n; i++)
#define rep(i,n) reps(i,0,n)
#define Rreps(i,n,e) for(int i = n - 1; i >= e; --i)
#define Rrep(i,n) Rreps(i,n,0)
#define ALL(a) a.begin(), a.end()
#define fi first
#define se second

using ll = long long;
using vec = vector<ll>;
using mat = vector<vec>;

ll N,M,H,W,Q,K,A,B;
string S;
typedef pair<ll, ll> P;
const ll INF = (1LL<<58);

template<class T> bool chmin(T &a, const T &b){
    if(a > b) {a = b; return true;}
    else return false;
}
template<class T> bool chmax(T &a, const T &b){
    if(a < b) {a = b; return true;}
    else return false;
}

template <unsigned long long mod > class modint{
public:
    ll x;
    constexpr modint(){x = 0;}
    constexpr modint(ll _x) : x((_x < 0 ? ((_x += (LLONG_MAX / mod) * mod) < 0 ? _x + (LLONG_MAX / mod) * mod : _x) : _x)%mod){}
    constexpr void set_raw(ll _x){
        //_x in [0, mod)
        x = _x;
    }
    constexpr modint operator-(){
        return x == 0 ? 0 : mod - x;
    }
    constexpr modint& operator+=(const modint& a){
        if((x += a.x) >= mod) x -= mod;
        return *this;
    }
    constexpr modint operator+(const modint& a) const{
        return modint(*this) += a;
    }
    constexpr modint& operator-=(const modint& a){
        if((x -= a.x) < 0) x += mod;
        return *this;
    }
    constexpr modint operator-(const modint& a) const{
        return modint(*this) -= a;
    }
    constexpr modint& operator*=(const modint& a){
        (x *= a.x)%=mod;
        return *this;
    }
    constexpr modint operator*(const modint& a) const{
        return modint(*this) *= a;
    }
    constexpr modint pow(unsigned long long pw) const{
        modint res(1), comp(*this);
        while(pw){
            if(pw&1) res *= comp;
            comp *= comp;
            pw >>= 1;
        }
        return res;
    }
    //以下、modが素数のときのみ
    constexpr modint inv() const{
        return modint(*this).pow(mod - 2);
    }
    constexpr modint& operator/=(const modint &a){
        (x *= a.inv().x)%=mod;
        return *this;
    }
    constexpr modint operator/(const modint &a) const{
        return modint(*this) /= a;
    }
};
#define mod1 998244353
using mint = modint<mod1>;

ostream& operator<<(ostream& os, const mint& a){
    os << a.x;
    return os;
}
using vm = vector<mint>;
class NTT{
    const int root;

    void make_root_pow(int n, vm &root_pow){
        root_pow.resize(n + 1);
        mint new_root = mint(root).pow((mod1 - 1) / n);
        root_pow[0].x = 1;
        rep(i,n){
            root_pow[i + 1] = root_pow[i] * new_root;
        }
    }
    static void make_bit_reverse(int n, vector<int> &v){
        v.resize(n);
        iota(ALL(v), 0);
        for(int i = 1; (1<<i) <= n; ++i){
            int l = 1<<(i - 1), r = 1<<i;
            int plus = n >> i;
            for(int j = l; j < r; ++j){
                int temp = v[j - l] + plus;
                if(j < temp) swap(v[j], v[temp]);
            }
        }
    }
    static void dft(int n, vm &f, bool inv, vm &root_pow, vector<int> &id){
        vm g(n);
        rep(i,n) g[i] = f[id[i]];
        swap(f, g);
        for(int l = n / 2, len = 1; l >= 1; l /= 2, len *= 2){
            for(int i = 0; i < n; i += len * 2){
                rep(j, len){
                    mint z_f = (inv ? root_pow[n - l * j] : root_pow[l * j]) * f[i + len + j];
                    g[i + j] = f[i + j] + z_f;
                    g[i + len + j] = f[i + j] - z_f;
                }
            }
            swap(f, g);
        }
        if(inv) {
            mint n_inv = mint(n).inv();
            rep(i, n) f[i] *= n_inv;
        }
    }
public:
    NTT(int _x = 3) : root(_x){}
    vm convolution(vm &a, vm &b, int size_a = INT_MAX, int size_b = INT_MAX){
        chmin(size_a, (int)a.size());
        chmin(size_b, (int)b.size());
        int sz = size_a + size_b - 1, n = 1;
        while(sz > n) n *= 2;
        vm g(n), h(n), root_pow, gh(n);
        vector<int> id;
        copy(a.begin(), a.begin() + size_a, g.begin());
        copy(b.begin(), b.begin() + size_b, h.begin());
        make_root_pow(n, root_pow);
        make_bit_reverse(n, id);
        dft(n, g, false, root_pow, id);
        dft(n, h, false, root_pow, id);
        rep(i, n) gh[i] = g[i] * h[i];
        dft(n, gh, true, root_pow, id);
        gh.resize(sz);
        return gh;
    }
};

vm polynomial_product(vector<vm> polys){
    //time complexity : O(N log^2 N) (N : sum of polys[i].size())
    struct _cmp{
        int sz;
        vm a;
        _cmp(int _sz, vm _a) : sz(_sz), a(_a){}
        bool operator > (const _cmp &b){ return sz > b.sz;}
    };
    priority_queue<_cmp, vector<_cmp>, greater<> > pque;
    for(vm a : polys) pque.emplace((int)a.size(), a);
    NTT ntt;
    while(pque.size() > 1){
        _cmp c = pque.top(); pque.pop();
        _cmp d = pque.top(); pque.pop();
        vm res = ntt.convolution(c.a, d.a);
        pque.emplace(res.size(), res);
    }
    return pque.top().a;
}

int main() {
    ll L, D;
    cin>>N>>L;
    vec t(N);
    rep(i, N) cin>>t[i];
    cin>>M>>D;
    vec x(M), p(M);
    rep(i, M) cin>>x[i]>>p[i];
    x.push_back(L);
    vector<vm> polys(0);
    rep(i, M){
        int d = x[i+1] - x[i];
        vm temp(d + 1);
        temp[d] = mint(p[i]) / 100;
        temp[0] = mint(1) - temp[d];
        polys.push_back(temp);
    }
    vm plus = polynomial_product(polys), plus_rev(plus);
    reverse(ALL(plus_rev));
    NTT ntt;
    vm diff = ntt.convolution(plus, plus_rev);
    ll n = (L - x[0]) * 2;
    rep(i, n) diff[i + 1] += diff[i];
    if(diff[n].x != 1) cout<<diff[n]<<endl;
    mint res(N);
    reps(i, 1, N){
        ll base_adv = L * (t[i] - t[0]);
        if(n * D <= base_adv) res -= 1;
        else if(base_adv >= - n * D) res -= diff[(base_adv + n * D) / (D * 2)];
    }
    cout<<res<<endl;
}
accuracy: 1
time_ms: 350
memory_kb: 26124
final_rank: 7

code_snippet: #include<iostream>
#include<vector>
#include<set>
#include<queue>
#include<map>
#include<algorithm>
#include<cstring>
#include<string>
#include<cassert>
#include<cmath>
#include<climits>
#include<iomanip>
#include<stack>
#include<unordered_map>
#include<bitset>
#include<limits>
#include<complex>
#include<array>
#include<numeric>
#include<functional>
#include<random>


using namespace std;
#define ll long long
#define ull unsigned long long
#define rep(i,m,n) for(ll (i)=(ll)(m);i<(ll)(n);i++)
#define REP(i,n) rep(i,0,n)
#define all(hoge) (hoge).begin(),(hoge).end()
typedef pair<ll, ll> P;
constexpr long double m_pi = 3.1415926535897932L;
constexpr ll MOD = 1000000007;
constexpr ll INF = 1LL << 61;
constexpr long double EPS = 1e-10;
template<typename T> using vector2 = vector<vector<T>>;
template<typename T> using vector3 = vector<vector2<T>>;
typedef vector<ll> Array;
typedef vector<Array> Matrix;
string operator*(const string& s, int k) {
	if (k == 0) return "";
	string p = (s + s) * (k / 2);
	if (k % 2 == 1) p += s;
	return p;
}

template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return true; }return false; }
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return true; }return false; }

struct Edge {//グラフ
	int to, rev; ll cap;
	Edge(int _to, ll _cap, int _rev) {
		to = _to; cap = _cap; rev = _rev;
	}
};
typedef vector<Edge> Edges;
typedef vector<Edges> Graph;
void add_edge(Graph& G, int from, int to, ll cap, bool revFlag, ll revCap) {//最大フロー求める Ford-fulkerson
	G[from].push_back(Edge(to, cap, (ll)G[to].size() + (from == to)));
	if (revFlag)G[to].push_back(Edge(from, revCap, (ll)G[from].size() - 1));//最小カットの場合逆辺は0にする
}

ll max_flow_dfs(Graph& G, ll v, ll t, ll f, vector<bool>& used)
{
	if (v == t)
		return f;
	used[v] = true;
	for (int i = 0; i < G[v].size(); ++i) {
		Edge& e = G[v][i];
		if (!used[e.to] && e.cap > 0) {
			ll d = max_flow_dfs(G, e.to, t, min(f, e.cap), used);
			if (d > 0) {
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
		}
	}
	return 0;
}
//二分グラフの最大マッチングを求めたりも出来る　また二部グラフの最大独立集合は頂点数-最大マッチングのサイズ
ll max_flow(Graph& G, ll s, ll t)//O(V(V+E))
{
	ll flow = 0;
	for (;;) {
		vector<bool> used(G.size());
		REP(i, used.size())used[i] = false;
		ll f = max_flow_dfs(G, s, t, INF, used);
		if (f == 0) {
			return flow;
		}
		flow += f;
	}
}

void BellmanFord(Graph& G, ll s, Array& d, Array& negative) {//O(|E||V|)
	d.resize(G.size());
	negative.resize(G.size());
	REP(i, d.size())d[i] = INF;
	REP(i, d.size())negative[i] = false;
	d[s] = 0;
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
				}
			}
		}
	}
	REP(k, G.size() - 1) {
		REP(i, G.size()) {
			REP(j, G[i].size()) {
				if (d[i] != INF && d[G[i][j].to] > d[i] + G[i][j].cap) {
					d[G[i][j].to] = d[i] + G[i][j].cap;
					negative[G[i][j].to] = true;
				}
				if (negative[i] == true)negative[G[i][j].to] = true;
			}
		}
	}
}
void Dijkstra(Graph& G, ll s, Array& d) {//O(|E|log|V|)
	d.resize(G.size());
	REP(i, d.size())d[i] = INF;
	d[s] = 0;
	priority_queue<P, vector<P>, greater<P>> q;
	q.push(make_pair(0, s));
	while (!q.empty()) {
		P a = q.top();
		q.pop();
		if (d[a.second] < a.first)continue;
		REP(i, G[a.second].size()) {
			Edge e = G[a.second][i];
			if (d[e.to] > d[a.second] + e.cap) {
				d[e.to] = d[a.second] + e.cap;
				q.push(make_pair(d[e.to], e.to));
			}
		}
	}
}
void WarshallFloyd(Graph& G, Matrix& d) {//O(V^3)
	d.resize(G.size());
	REP(i, d.size())d[i].resize(G.size());
	REP(i, d.size()) {
		REP(j, d[i].size()) {
			d[i][j] = ((i != j) ? INF : 0);
		}
	}
	REP(i, G.size()) {
		REP(j, G[i].size()) {
			chmin(d[i][G[i][j].to], G[i][j].cap);
		}
	}
	REP(i, G.size()) {
		REP(j, G.size()) {
			REP(k, G.size()) {
				if (d[j][i] != INF && d[i][k] != INF)chmin(d[j][k], d[j][i] + d[i][k]);
			}
		}
	}
}
bool tsort(Graph& graph, vector<int>& order) {//トポロジカルソートO(E+V)
	int n = graph.size(), k = 0;
	vector<int> in(n);
	for (auto& es : graph)
		for (auto& e : es)in[e.to]++;
	priority_queue<int, vector<int>, greater<int>> que;
	REP(i, n)
		if (in[i] == 0)que.push(i);
	while (que.size()) {
		int v = que.top();
		que.pop();
		order.push_back(v);
		for (auto& e : graph[v])
			if (--in[e.to] == 0)que.push(e.to);
	}
	if (order.size() != n)return false;
	else return true;
}
class Lca {
public:
	const int n = 0;
	const int log2_n = 0;
	std::vector<std::vector<int>> parent;
	std::vector<int> depth;

	Lca() {}

	Lca(const Graph& g, int root)
		: n(g.size()), log2_n(log2(n) + 1), parent(log2_n, std::vector<int>(n)), depth(n) {
		dfs(g, root, -1, 0);
		for (int k = 0; k + 1 < log2_n; k++) {
			for (int v = 0; v < (int)g.size(); v++) {
				if (parent[k][v] < 0)
					parent[k + 1][v] = -1;
				else
					parent[k + 1][v] = parent[k][parent[k][v]];
			}
		}
	}

	void dfs(const Graph& g, int v, int p, int d) {
		parent[0][v] = p;
		depth[v] = d;
		for (auto& e : g[v]) {
			if (e.to != p) dfs(g, e.to, v, d + 1);
		}
	}

	int get(int u, int v) {
		if (depth[u] > depth[v]) std::swap(u, v);
		for (int k = 0; k < log2_n; k++) {
			if ((depth[v] - depth[u]) >> k & 1) {
				v = parent[k][v];
			}
		}
		if (u == v) return u;
		for (int k = log2_n - 1; k >= 0; k--) {
			if (parent[k][u] != parent[k][v]) {
				u = parent[k][u];
				v = parent[k][v];
			}
		}
		return parent[0][u];
	}
};

class UnionFind {
	vector<int> data;
	int n;
public:
	UnionFind(int size) : data(size, -1), n(size) { }
	bool merge(int x, int y) {//xとyの集合を統合する
		x = root(x); y = root(y);
		if (x != y) {
			if (data[y] < data[x]) swap(x, y);
			data[x] += data[y]; data[y] = x;
		}
		n -= (x != y);
		return x != y;
	}
	bool same(int x, int y) {//xとyが同じ集合か返す
		return root(x) == root(y);
	}
	int root(int x) {//xのルートを返す
		return data[x] < 0 ? x : data[x] = root(data[x]);
	}
	int size(int x) {//xの集合のサイズを返す
		return -data[root(x)];
	}
	int num() {//集合の数を返す
		return n;
	}
};

template<typename T, typename F>
class SegmentTree {
private:
	T identity;
	F merge;
	ll n;
	vector<T> dat;
public:
	SegmentTree(F f, T id, vector<T> v) :merge(f), identity(id) {
		int _n = v.size();
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
		REP(i, _n)dat[n + i - 1] = v[i];
		for (int i = n - 2; i >= 0; i--)dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
	}
	SegmentTree(F f, T id, int _n) :merge(f), identity(id) {
		n = 1;
		while (n < _n)n *= 2;
		dat.resize(2 * n - 1, identity);
	}
	void set_val(int i, T x) {
		i += n - 1;
		dat[i] = x;
		while (i > 0) {
			i = (i - 1) / 2;
			dat[i] = merge(dat[i * 2 + 1], dat[i * 2 + 2]);
		}
	}
	T query(int l, int r) {
		T left = identity, right = identity;
		l += n - 1; r += n - 1;
		while (l < r) {
			if ((l & 1) == 0)left = merge(left, dat[l]);
			if ((r & 1) == 0)right = merge(dat[r - 1], right);
			l = l / 2;
			r = (r - 1) / 2;
		}
		return merge(left, right);
	}
};

template< typename T >
class FenwickTree {
	vector< T > data;
	int n;
	int p;
public:
	FenwickTree(int n) :n(n) {
		data.resize(n + 1LL, 0);
		p = 1;
		while (p < data.size())p *= 2;
	}
	T sum(int k) {
		T ret = 0;
		for (; k > 0; k -= k & -k) ret += data[k];
		return (ret);
	}

	T sum(int a, int b) { return sum(b) - sum(a); }//[a,b)

	void add(int k, T x) {
		for (++k; k <= n; k += k & -k) data[k] += x;
	}

	int lower_bound(ll w) {
		if (w <= 0)return -1;
		int x = 0;
		for (int k = p / 2; k > 0; k /= 2) {
			if (x + k <= n && data[x + k] < w)w -= data[x + k], x += k;
		}
		return x;
	}
};



//約数求める //約数
void divisor(ll n, vector<ll>& ret) {
	for (ll i = 1; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back(i);
			if (i * i != n) ret.push_back(n / i);
		}
	}
	sort(ret.begin(), ret.end());
}

void prime_factorization(ll n, vector<P>& ret) {
	for (ll i = 2; i * i <= n; i++) {
		if (n % i == 0) {
			ret.push_back({ i,0 });
			while (n % i == 0) {
				n /= i;
				ret[ret.size() - 1].second++;
			}
		}
	}
	if (n != 1)ret.push_back({ n,1 });
}


inline ll mod_pow(ll x, ll n, ll mod) {
	ll res = 1;
	while (n > 0) {
		if (n & 1) res = res * x % mod;
		x = x * x % mod;
		n >>= 1;
	}
	return res;
}

inline ll mod_inv(ll x, ll mod) {
	return mod_pow(x, mod - 2, mod);
}

class Combination {
public:
	Array fact;
	Array fact_inv;
	ll mod;
	//if n >= mod use lucas 
	ll nCr(ll n, ll r) {
		if (n < r)return 0;
		if (n < mod)return ((fact[n] * fact_inv[r] % mod) * fact_inv[n - r]) % mod;

		ll ret = 1;
		while (n || r) {
			ll _n = n % mod, _r = r % mod;
			n /= mod; r /= mod;
			(ret *= nCr(_n, _r)) %= mod;
		}
		return ret;
	}
	ll nPr(ll n, ll r) {
		return (fact[n] * fact_inv[n - r]) % mod;
	}
	ll nHr(ll n, ll r) {
		return nCr(r + n - 1, r);
	}
	Combination(ll _n, ll _mod) {
		mod = _mod;
		ll n = min(_n + 1, mod);
		fact.resize(n);
		fact[0] = 1;
		REP(i, n - 1) {
			fact[i + 1] = (fact[i] * (i + 1LL)) % mod;
		}
		fact_inv.resize(n);
		fact_inv[n - 1] = mod_inv(fact[n - 1], mod);
		for (int i = n - 1; i > 0; i--) {
			fact_inv[i - 1] = fact_inv[i] * i % mod;
		}
	}
};

ll popcount(ll x) {
	x = (x & 0x5555555555555555) + (x >> 1 & 0x5555555555555555);
	x = (x & 0x3333333333333333) + (x >> 2 & 0x3333333333333333);
	x = (x & 0x0F0F0F0F0F0F0F0F) + (x >> 4 & 0x0F0F0F0F0F0F0F0F);
	x = (x & 0x00FF00FF00FF00FF) + (x >> 8 & 0x00FF00FF00FF00FF);
	x = (x & 0x0000FFFF0000FFFF) + (x >> 16 & 0x0000FFFF0000FFFF);
	x = (x & 0x00000000FFFFFFFF) + (x >> 32 & 0x00000000FFFFFFFF);

	return x;
}



template<ll mod, ll root>//特殊な素数と原始根　998244353のとき3
class NTT {
private:
	template<typename T>
	inline void bit_reverse(vector<T>& a) {
		int n = a.size();
		int i = 0;
		for (int j = 1; j < n - 1; ++j) {
			for (int k = n >> 1; k > (i ^= k); k >>= 1);
			if (j < i) swap(a[i], a[j]);
		}
	}
	void _ntt(vector<long long>& a, int sign) {
		const int n = a.size();
		assert((n ^ (n & -n)) == 0); //n = 2^k

		long long tmp = (mod - 1) * mod_pow((ll)n, mod - 2, mod) % mod; // -1/n
		long long h = mod_pow(root, tmp, mod); // ^n√g
		if (sign == -1) h = mod_pow(h, mod - 2, mod);

		bit_reverse(a);

		for (ll m = 1; m < n; m <<= 1) {
			const ll m2 = 2 * m;
			long long _base = mod_pow((ll)h, (ll)(n / m2), mod);
			long long _w = 1;
			for (int x = 0; x < m; ++x) {//計算量わからない
				for (ll s = x; s < n; s += m2) {
					long long u = a[s];
					long long d = (a[s + m] * _w) % mod;
					a[s] = (u + d) % mod;
					a[s + m] = (u - d + mod) % mod;
				}
				_w = (_w * _base) % mod;
			}
		}
	}

	void ntt(vector<long long>& input) { _ntt(input, 1); }//フーリエ変換

	void intt(vector<long long>& input) {//フーリエ逆変換
		_ntt(input, -1);
		const long long n_inv = mod_pow((ll)input.size(), mod - 2, mod);
		for (auto& x : input) x = (x * n_inv) % mod;
	}
public:
	// 畳み込み演算を行う
	vector<long long> convolution(const vector<long long>& a, const vector<long long>& b) {
		int result_size = a.size() + b.size() - 1;
		int n = 1; while (n < result_size) n <<= 1;

		vector<long long> _a = a, _b = b;
		_a.resize(n, 0);
		_b.resize(n, 0);

		ntt(_a);
		ntt(_b);
		for (int i = 0; i < n; ++i) _a[i] = (_a[i] * _b[i]) % mod;
		intt(_a);

		_a.resize(result_size);
		return _a;
	}
	vector<long long> convolution(const vector<long long>& a, ll m, ll mx_sz) {//多項式に落とし込めるdpが解ける
		int result_size = mx_sz;
		int n = 1; while (n < result_size) n <<= 1;

		vector<long long> _a = a;
		_a.resize(n, 0);

		ntt(_a);
		for (int i = 0; i < n; ++i) _a[i] = mod_pow(_a[i], m, mod);
		intt(_a);

		_a.resize(result_size);
		return _a;
	}
};

int main() {
	ios::sync_with_stdio(false);
	std::cin.tie(0);
	std::cout.tie(0);

	constexpr ll mod = 998244353;
	ll n, l;
	cin >> n >> l;
	Array t(n);
	for (auto& e : t)cin >> e;
	ll m, d;
	cin >> m >> d;
	Array x(m), p(m);
	x.push_back(l);
	REP(i, m)cin >> x[i] >> p[i];
	deque<Array> c;
	REP(i, m) {
		Array tmp(2 * (x[i + 1] - x[i]) + 1, 0);
		tmp[0] = p[i];
		tmp.back() = 100 - p[i];
		c.emplace_back(tmp);
	}
	NTT<998244353, 3> ntt;
	while (c.size() > 1) {
		auto a = c.front();
		c.pop_front();
		auto b = c.front();
		c.pop_front();
		c.emplace_back(ntt.convolution(a, b));
	}
	Array u(4 * l + 4, 0), v(4 * l + 4, 0);
	u[2 * l + 1] = 1;
	rep(i, 1, n) {
		ll dif = (t[0] - t[i]) * l;
		if (dif >= 0) {
			dif = min((dif + d - 1) / d, 2 * l + 1);
			v[2 * l + 1 - dif]++;
		}
		else {
			dif *= -1;
			dif = min(dif / d + (dif%(2*d)==0?1:0), 2 * l + 1);
			v[2 * l + 1 + dif]++;
		}
	}
	//for (auto e : u)cout << e << " ";
	//cout << endl;
	//for (auto e : v)cout << e << " ";
	//cout << endl;
	u = ntt.convolution(u, c.front());
	v = ntt.convolution(v, c.front());
	//for (auto e : u)cout << e << " ";
	//cout << endl;
	//for (auto e : v)cout << e << " ";
	//cout << endl;

	ll ans = 0;
	ll total = accumulate(all(u), 0LL, [&](ll a, ll b) {return (a + b) % mod; });
	ll now = 0;
	REP(i, u.size()) {
		if (u[i] != 0) (ans += (now * mod_inv(total, mod) % mod) % mod * u[i] % mod) %= mod;
		(now += v[i]) %= mod;
	}
//	cout << ans << "\n";
	cout << (1 + ans * mod_inv(total, mod) % mod) % mod << "\n";


	return 0;
}
accuracy: 1
time_ms: 1110
memory_kb: 46324
final_rank: 12

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

// modint
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() const { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    constexpr bool operator < (const Fp& r) const noexcept {
        return this->val < r.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

namespace NTT {
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    template<class mint> void trans(vector<mint> &v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static bool first = true;
        static vector<long long> vbw(30), vibw(30);
        if (first) {
            first = false;
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T> &A, const vector<T> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> operator * 
    (const vector<mint> &A, const vector<mint> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 30) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        vector<mint> a(size_fft), b(size_fft), c(size_fft);
        for (int i = 0; i < N; ++i) a[i] = A[i];
        for (int i = 0; i < M; ++i) b[i] = B[i];
        trans(a), trans(b);
        vector<mint> res(size_fft);
        for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
        trans(res, true);
        res.resize(N + M - 1);
        return res;
    }
};

const int MOD = 998244353;
using mint = Fp<MOD>;
using namespace NTT;


int main() {
    long long N, L, M, D;
    cin >> N >> L;
    vector<long long> t(N);
    for (int i = 0; i < N; ++i) cin >> t[i];
    cin >> M >> D;
    vector<long long> x(M + 1, L);
    vector<mint> p(M);
    for (int i = 0; i < M; ++i) cin >> x[i] >> p[i], p[i] /= 100;

    priority_queue<pair<int,vector<mint>>, vector<pair<int,vector<mint>>>, greater<pair<int,vector<mint>>>> que;
    for (int i = 0; i < M; ++i) {
        long long l = x[i+1] - x[i];
        vector<mint> v(l+1, 0);
        v[0] = mint(1) - p[i];
        v[l] = p[i];
        que.push({l+1, v});
    }
    while (que.size() >= 2) {
        auto left = que.top(); que.pop();
        auto right = que.top(); que.pop();
        auto mul = left.second * right.second;
        que.push({mul.size(), mul});
    }
    auto f = que.top().second;
    long long deg = f.size() - 1;
    auto g = f;
    reverse(g.begin(), g.end());
    auto fg = f * g;
    vector<mint> sum(fg.size()+1, 0);
    for (int i = 0; i < fg.size(); ++i) sum[i+1] = sum[i] + fg[i];

    mint res = 1;
    for (int i = 1; i < N; ++i) {
        long long lim = deg + (L * (t[0] - t[i]) + D * 20000000 + D * 2 - 1) / (D * 2) - 10000000;
        chmax(lim, 0LL);
        chmin(lim, (long long)sum.size() - 1);
        res += sum[lim];
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 360
memory_kb: 20028
final_rank: 4

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


// modint
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() const { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    constexpr bool operator < (const Fp& r) const noexcept {
        return this->val < r.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

namespace NTT {
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    template<class mint> void trans(vector<mint> &v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static bool first = true;
        static vector<long long> vbw(30), vibw(30);
        if (first) {
            first = false;
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int MOD0 = 754974721;
    static constexpr int MOD1 = 167772161;
    static constexpr int MOD2 = 469762049;
    using mint0 = Fp<MOD0>;
    using mint1 = Fp<MOD1>;
    using mint2 = Fp<MOD2>;
    static const mint1 imod0 = 95869806; // modinv(MOD0, MOD1);
    static const mint2 imod1 = 104391568; // modinv(MOD1, MOD2);
    static const mint2 imod01 = 187290749; // imod1 / MOD0;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T> &A, const vector<T> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> operator * 
    (const vector<mint> &A, const vector<mint> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 30) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint0> a0(size_fft, 0), b0(size_fft, 0), c0(size_fft, 0);
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a0[i] = A[i].val, a1[i] = A[i].val, a2[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b0[i] = B[i].val, b1[i] = B[i].val, b2[i] = B[i].val;
        trans(a0), trans(a1), trans(a2), trans(b0), trans(b1), trans(b2);
        for (int i = 0; i < size_fft; ++i) {
            c0[i] = a0[i] * b0[i];
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
        }
        trans(c0, true), trans(c1, true), trans(c2, true);
        static const mint mod0 = MOD0, mod01 = mod0 * MOD1;
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y0 = c0[i].val;
            int y1 = (imod0 * (c1[i] - y0)).val;
            int y2 = (imod01 * (c2[i] - y0) - imod1 * y1).val;
            res[i] = mod01 * y2 + mod0 * y1 + y0;
        }
        return res;
    }

    // long long
    vector<long long> mul
    (const vector<long long> &A, const vector<long long> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 30) return naive_mul(A, B);
        int size_fft = get_fft_size(N, M);
        vector<mint0> a0(size_fft, 0), b0(size_fft, 0), c0(size_fft, 0);
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a0[i] = A[i], a1[i] = A[i], a2[i] = A[i];
        for (int i = 0; i < M; ++i)
            b0[i] = B[i], b1[i] = B[i], b2[i] = B[i];
        trans(a0), trans(a1), trans(a2), trans(b0), trans(b1), trans(b2);
        for (int i = 0; i < size_fft; ++i) {
            c0[i] = a0[i] * b0[i];
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
        }
        trans(c0, true), trans(c1, true), trans(c2, true);
        static const long long mod0 = MOD0, mod01 = mod0 * MOD1;
        vector<long long> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y0 = c0[i].val;
            int y1 = (imod0 * (c1[i] - y0)).val;
            int y2 = (imod01 * (c2[i] - y0) - imod1 * y1).val;
            res[i] = mod01 * y2 + mod0 * y1 + y0;
        }
        return res;
    }
};

const int MOD = 998244353;
using mint = Fp<MOD>;
using namespace NTT;


int main() {
    long long N, L, M, D;
    cin >> N >> L;
    vector<long long> t(N);
    for (int i = 0; i < N; ++i) cin >> t[i];
    cin >> M >> D;
    vector<long long> x(M + 1, L);
    vector<mint> p(M);
    for (int i = 0; i < M; ++i) cin >> x[i] >> p[i], p[i] /= 100;

    priority_queue<pair<int,vector<mint>>, vector<pair<int,vector<mint>>>, greater<pair<int,vector<mint>>>> que;
    for (int i = 0; i < M; ++i) {
        long long l = x[i+1] - x[i];
        vector<mint> v(l+1, 0);
        v[0] = mint(1) - p[i];
        v[l] = p[i];
        que.push({l+1, v});
    }
    while (que.size() >= 2) {
        auto left = que.top(); que.pop();
        auto right = que.top(); que.pop();
        auto mul = left.second * right.second;
        que.push({mul.size(), mul});
    }
    auto f = que.top().second;
    long long deg = f.size() - 1;
    auto g = f;
    reverse(g.begin(), g.end());
    auto fg = f * g;
    int size = fg.size();
    vector<mint> sum(size+1, 0);
    for (int i = 0; i < size; ++i) sum[i+1] = sum[i] + fg[i];

    mint res = 1;
    for (int i = 1; i < N; ++i) {
        long long lim = deg + (L * (t[0] - t[i]) + D * 20000000 + D * 2 - 1) / (D * 2) - 10000000;
        chmax(lim, 0LL);
        chmin(lim, (long long)sum.size() - 1);
        res += sum[lim];

        //cout << i << ": " << lim << endl;
    }
    cout << res << endl;
}
accuracy: 1
time_ms: 400
memory_kb: 20024
final_rank: 5

code_snippet: #include <bits/stdc++.h>
using namespace std;
template<class T> inline bool chmax(T& a, T b) { if (a < b) { a = b; return 1; } return 0; }
template<class T> inline bool chmin(T& a, T b) { if (a > b) { a = b; return 1; } return 0; }

#define COUT(x) cout << #x << " = " << (x) << " (L" << __LINE__ << ")" << endl
template<class T1, class T2> ostream& operator << (ostream &s, pair<T1,T2> P)
{ return s << '<' << P.first << ", " << P.second << '>'; }
template<class T> ostream& operator << (ostream &s, vector<T> P)
{ for (int i = 0; i < P.size(); ++i) { if (i > 0) { s << " "; } s << P[i]; } return s; }
template<class T> ostream& operator << (ostream &s, vector<vector<T> > P)
{ for (int i = 0; i < P.size(); ++i) { s << endl << P[i]; } return s << endl; }
template<class T> ostream& operator << (ostream &s, set<T> P)
{ for(auto it : P) { s << "<" << it << "> "; } return s << endl; }
template<class T1, class T2> ostream& operator << (ostream &s, map<T1,T2> P)
{ for(auto it : P) { s << "<" << it.first << "->" << it.second << "> "; } return s << endl; }


// modint
template<int MOD> struct Fp {
    long long val;
    constexpr Fp(long long v = 0) noexcept : val(v % MOD) {
        if (val < 0) val += MOD;
    }
    constexpr int getmod() const { return MOD; }
    constexpr Fp operator - () const noexcept {
        return val ? MOD - val : 0;
    }
    constexpr Fp operator + (const Fp& r) const noexcept { return Fp(*this) += r; }
    constexpr Fp operator - (const Fp& r) const noexcept { return Fp(*this) -= r; }
    constexpr Fp operator * (const Fp& r) const noexcept { return Fp(*this) *= r; }
    constexpr Fp operator / (const Fp& r) const noexcept { return Fp(*this) /= r; }
    constexpr Fp& operator += (const Fp& r) noexcept {
        val += r.val;
        if (val >= MOD) val -= MOD;
        return *this;
    }
    constexpr Fp& operator -= (const Fp& r) noexcept {
        val -= r.val;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr Fp& operator *= (const Fp& r) noexcept {
        val = val * r.val % MOD;
        return *this;
    }
    constexpr Fp& operator /= (const Fp& r) noexcept {
        long long a = r.val, b = MOD, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        val = val * u % MOD;
        if (val < 0) val += MOD;
        return *this;
    }
    constexpr bool operator == (const Fp& r) const noexcept {
        return this->val == r.val;
    }
    constexpr bool operator != (const Fp& r) const noexcept {
        return this->val != r.val;
    }
    constexpr bool operator < (const Fp& r) const noexcept {
        return this->val < r.val;
    }
    friend constexpr istream& operator >> (istream &is, Fp<MOD>& x) noexcept {
        is >> x.val;
        x.val %= MOD;
        if (x.val < 0) x.val += MOD;
        return is;
    }
    friend constexpr ostream& operator << (ostream &os, const Fp<MOD>& x) noexcept {
        return os << x.val;
    }
    friend constexpr Fp<MOD> modpow(const Fp<MOD> &a, long long n) noexcept {
        if (n == 0) return 1;
        auto t = modpow(a, n / 2);
        t = t * t;
        if (n & 1) t = t * a;
        return t;
    }
};

namespace NTT {
    long long modpow(long long a, long long n, int mod) {
        long long res = 1;
        while (n > 0) {
            if (n & 1) res = res * a % mod;
            a = a * a % mod;
            n >>= 1;
        }
        return res;
    }

    long long modinv(long long a, int mod) {
        long long b = mod, u = 1, v = 0;
        while (b) {
            long long t = a / b;
            a -= t * b, swap(a, b);
            u -= t * v, swap(u, v);
        }
        u %= mod;
        if (u < 0) u += mod;
        return u;
    }

    int calc_primitive_root(int mod) {
        if (mod == 2) return 1;
        if (mod == 167772161) return 3;
        if (mod == 469762049) return 3;
        if (mod == 754974721) return 11;
        if (mod == 998244353) return 3;
        int divs[20] = {};
        divs[0] = 2;
        int cnt = 1;
        long long x = (mod - 1) / 2;
        while (x % 2 == 0) x /= 2;
        for (long long i = 3; i * i <= x; i += 2) {
            if (x % i == 0) {
                divs[cnt++] = i;
                while (x % i == 0) x /= i;
            }
        }
        if (x > 1) divs[cnt++] = x;
        for (int g = 2;; g++) {
            bool ok = true;
            for (int i = 0; i < cnt; i++) {
                if (modpow(g, (mod - 1) / divs[i], mod) == 1) {
                    ok = false;
                    break;
                }
            }
            if (ok) return g;
        }
    }

    int get_fft_size(int N, int M) {
        int size_a = 1, size_b = 1;
        while (size_a < N) size_a <<= 1;
        while (size_b < M) size_b <<= 1;
        return max(size_a, size_b) << 1;
    }

    // number-theoretic transform
    template<class mint> void trans(vector<mint> &v, bool inv = false) {
        if (v.empty()) return;
        int N = (int)v.size();
        int MOD = v[0].getmod();
        int PR = calc_primitive_root(MOD);
        static bool first = true;
        static vector<long long> vbw(30), vibw(30);
        if (first) {
            first = false;
            for (int k = 0; k < 30; ++k) {
                vbw[k] = modpow(PR, (MOD - 1) >> (k + 1), MOD);
                vibw[k] = modinv(vbw[k], MOD);
            }
        }
        for (int i = 0, j = 1; j < N - 1; j++) {
            for (int k = N >> 1; k > (i ^= k); k >>= 1);
            if (i > j) swap(v[i], v[j]);
        }
        for (int k = 0, t = 2; t <= N; ++k, t <<= 1) {
            long long bw = vbw[k];
            if (inv) bw = vibw[k];
            for (int i = 0; i < N; i += t) {
                mint w = 1;
                for (int j = 0; j < t/2; ++j) {
                    int j1 = i + j, j2 = i + j + t/2;
                    mint c1 = v[j1], c2 = v[j2] * w;
                    v[j1] = c1 + c2;
                    v[j2] = c1 - c2;
                    w *= bw;
                }
            }
        }
        if (inv) {
            long long invN = modinv(N, MOD);
            for (int i = 0; i < N; ++i) v[i] = v[i] * invN;
        }
    }

    // for garner
    static constexpr int MOD0 = 754974721;
    static constexpr int MOD1 = 167772161;
    static constexpr int MOD2 = 469762049;
    using mint0 = Fp<MOD0>;
    using mint1 = Fp<MOD1>;
    using mint2 = Fp<MOD2>;
    static const mint1 imod0 = 95869806; // modinv(MOD0, MOD1);
    static const mint2 imod1 = 104391568; // modinv(MOD1, MOD2);
    static const mint2 imod01 = 187290749; // imod1 / MOD0;

    // small case (T = mint, long long)
    template<class T> vector<T> naive_mul 
    (const vector<T> &A, const vector<T> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        vector<T> res(N + M - 1);
        for (int i = 0; i < N; ++i)
            for (int j = 0; j < M; ++j)
                res[i + j] += A[i] * B[j];
        return res;
    }

    // mint
    template<class mint> vector<mint> operator * 
    (const vector<mint> &A, const vector<mint> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 30) return naive_mul(A, B);
        int MOD = A[0].getmod();
        int size_fft = get_fft_size(N, M);
        if (MOD == 998244353) {
            vector<mint> a(size_fft), b(size_fft), c(size_fft);
            for (int i = 0; i < N; ++i) a[i] = A[i];
            for (int i = 0; i < M; ++i) b[i] = B[i];
            trans(a), trans(b);
            vector<mint> res(size_fft);
            for (int i = 0; i < size_fft; ++i) res[i] = a[i] * b[i];
            trans(res, true);
            res.resize(N + M - 1);
            return res;
        }
        vector<mint0> a0(size_fft, 0), b0(size_fft, 0), c0(size_fft, 0);
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a0[i] = A[i].val, a1[i] = A[i].val, a2[i] = A[i].val;
        for (int i = 0; i < M; ++i)
            b0[i] = B[i].val, b1[i] = B[i].val, b2[i] = B[i].val;
        trans(a0), trans(a1), trans(a2), trans(b0), trans(b1), trans(b2);
        for (int i = 0; i < size_fft; ++i) {
            c0[i] = a0[i] * b0[i];
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
        }
        trans(c0, true), trans(c1, true), trans(c2, true);
        static const mint mod0 = MOD0, mod01 = mod0 * MOD1;
        vector<mint> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y0 = c0[i].val;
            int y1 = (imod0 * (c1[i] - y0)).val;
            int y2 = (imod01 * (c2[i] - y0) - imod1 * y1).val;
            res[i] = mod01 * y2 + mod0 * y1 + y0;
        }
        return res;
    }

    // long long
    vector<long long> mul
    (const vector<long long> &A, const vector<long long> &B) {
        if (A.empty() || B.empty()) return {};
        int N = (int)A.size(), M = (int)B.size();
        if (min(N, M) < 30) return naive_mul(A, B);
        int size_fft = get_fft_size(N, M);
        vector<mint0> a0(size_fft, 0), b0(size_fft, 0), c0(size_fft, 0);
        vector<mint1> a1(size_fft, 0), b1(size_fft, 0), c1(size_fft, 0);
        vector<mint2> a2(size_fft, 0), b2(size_fft, 0), c2(size_fft, 0);
        for (int i = 0; i < N; ++i)
            a0[i] = A[i], a1[i] = A[i], a2[i] = A[i];
        for (int i = 0; i < M; ++i)
            b0[i] = B[i], b1[i] = B[i], b2[i] = B[i];
        trans(a0), trans(a1), trans(a2), trans(b0), trans(b1), trans(b2);
        for (int i = 0; i < size_fft; ++i) {
            c0[i] = a0[i] * b0[i];
            c1[i] = a1[i] * b1[i];
            c2[i] = a2[i] * b2[i];
        }
        trans(c0, true), trans(c1, true), trans(c2, true);
        static const long long mod0 = MOD0, mod01 = mod0 * MOD1;
        vector<long long> res(N + M - 1);
        for (int i = 0; i < N + M - 1; ++i) {
            int y0 = c0[i].val;
            int y1 = (imod0 * (c1[i] - y0)).val;
            int y2 = (imod01 * (c2[i] - y0) - imod1 * y1).val;
            res[i] = mod01 * y2 + mod0 * y1 + y0;
        }
        return res;
    }
};

const int MOD = 998244353;
using mint = Fp<MOD>;
using namespace NTT;


int main() {
    long long N, L, M, D;
    cin >> N >> L;
    vector<long long> t(N);
    for (int i = 0; i < N; ++i) cin >> t[i];
    cin >> M >> D;
    vector<long long> x(M + 1, L);
    vector<mint> p(M);
    for (int i = 0; i < M; ++i) cin >> x[i] >> p[i], p[i] /= 100;

    priority_queue<pair<int,vector<mint>>, vector<pair<int,vector<mint>>>, greater<pair<int,vector<mint>>>> que;
    for (int i = 0; i < M; ++i) {
        long long l = x[i+1] - x[i];
        vector<mint> v(l+1, 0);
        v[0] = mint(1) - p[i];
        v[l] = p[i];
        que.push({l+1, v});
    }
    while (que.size() >= 2) {
        auto left = que.top(); que.pop();
        auto right = que.top(); que.pop();
        auto mul = left.second * right.second;
        que.push({mul.size(), mul});
    }
    auto f = que.top().second;
    int deg = f.size() - 1;
    auto g = f;
    reverse(g.begin(), g.end());
    auto fg = f * g;
    int size = fg.size();
    vector<mint> sum(size+1, 0);
    for (int i = 0; i < size; ++i) sum[i+1] = sum[i] + fg[i];

    mint res = 1;
    for (int i = 1; i < N; ++i) {
        int lim = deg + (L * (t[0] - t[i]) + D * 20000000 + D * 2 - 1) / (D * 2) - 10000000;
        chmax(lim, 0);
        chmin(lim, (int)sum.size() - 1);
        res += sum[lim];
    }
    cout << res << endl;
}
accuracy: 0.6
time_ms: 370
memory_kb: 19960
final_rank: 13

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <tuple>
#define mkp make_pair
#define mkt make_tuple
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
const ll MOD=998244353;
template<class T> void chmin(T &a,const T &b){if(a>b) a=b;}
template<class T> void chmax(T &a,const T &b){if(a<b) a=b;}

ll mod_pow(ll x,ll n){
  x%=MOD;
  ll res=1;
  while(n>0){
    if(n&1) res=res*x%MOD;
    x=x*x%MOD;
    n>>=1;
  }
  return res;
}

ll mod_inverse(ll x){
  return mod_pow(x,MOD-2);
}

void add(ll &a,ll b){
  a=(a+b)%MOD;
}

void mul(ll &a,ll b){
  a%=MOD;b%=MOD;
  a=a*b%MOD;
}

//const ll MOD=998244353; // MOD == 119*2^23+1
//depends on mod_pow,mod_inverse

ll root[24],invroot[24];

void NTT_init(){
    for(int i=0;i<24;++i){
        root[i]=mod_pow(3,(MOD-1)/(1<<i));
        invroot[i]=mod_inverse(root[i]);
    }
}

vector<ll> NTT(vector<ll> a,bool inverse=false){
    int n=a.size();
    int high=0;
    for(int i=0;(1<<i)<n;++i) high++;

    for(int i=0;i<n;++i){
        int mask=0;
        for(int k=0;k<high;++k){
            if(i>>k&1) mask|=(1<<(high-1-k));
        }
        if(i<mask) swap(a[i],a[mask]);
    }

    for(int j=1;(1<<j)<=n;++j){
        int m=(1<<j);
        ll zeta=root[j];
        if(inverse) zeta=invroot[j];
        for(int i=0;i<n;i+=m){
            ll powzeta=1;
            for(int k=i;k<i+m/2;++k){
                ll s=a[k];
                ll t=a[k+m/2]*powzeta%MOD;

                a[k]=(s+t)%MOD;
                a[k+m/2]=(s-t+MOD)%MOD;
                powzeta=powzeta*zeta%MOD;
            }
        }
    }

    if(inverse){
        ll invn=mod_inverse(n);
        for(int i=0;i<n;++i) a[i]=a[i]*invn%MOD;
    }
    return a;
}

vector<ll> convolute(const vector<ll> &a,const vector<ll> &b){
    int size=a.size()+b.size()-1;
    int n=1;
    while(n<size) n<<=1;

    vector<ll> A(n,0),B(n,0);
    for(int i=0;i<a.size();i++) A[i]=a[i];
    for(int i=0;i<b.size();i++) B[i]=b[i];

    A=NTT(A);
    B=NTT(B);

    for(int i=0;i<n;++i) A[i]=A[i]*B[i]%MOD;
    A=NTT(A,true);

    A.resize(size);
    return A;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N;
  ll L;
  cin>>N>>L;
  vector<ll> T(N);
  rep(i,N) cin>>T[i];
  int M;
  ll D;
  cin>>M>>D;
  vector<ll> X(M+1),P(M+1);
  rep(i,M) cin>>X[i]>>P[i];
  X[M]=L;

  NTT_init();

  ll inv100=mod_inverse(100);
  vector<vector<ll>> B(M);
  rep(i,M){
      int diff=X[i+1]-X[i];
      B[i].resize(diff+1,0);
      B[i][0]=P[i]*inv100%MOD;
      B[i][diff]=(100-P[i])*inv100%MOD;
  }

  priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> PQ;
  rep(i,M) PQ.push(mkp(B[i].size(),i));
  while(PQ.size()>1){
      auto f=PQ.top();
      PQ.pop();
      auto s=PQ.top();
      PQ.pop();

      int ft=f.second;
      int st=s.second;
      B[ft]=convolute(B[ft],B[st]);
      B[st].clear();

      PQ.push(mkp(B[ft].size(),ft));
  }

  auto f=PQ.top();PQ.pop();
  vector<ll> dist=B[f.second];
  int SZ=dist.size();

  vector<ll> revd=dist;
  reverse(all(revd));
  dist=convolute(dist,revd);

  int V=dist.size();
  vector<ll> rsum(V+1,0);
  for(int i=V-1;i>=0;i--) rsum[i]=(rsum[i+1]+dist[i])%MOD;

  ll ans=0;
  for(int i=1;i<N;i++){
      ll border=(L*abs(T[0]-T[i])+2*D-1)/(2*D);
      if(T[0]-T[i]<0) border*=(-1);
      if(T[0]-T[i]<0&&(L*abs(T[0]-T[i]))%(2*D)) ++border;
      if(border+SZ-1>V) continue;
      add(ans,rsum[max(0ll,border+SZ-1)]);
  }
  ans=(N-ans+MOD)%MOD;
  add(ans,MOD);
  cout<<ans<<endl;


  return 0;
}
accuracy: 1
time_ms: 540
memory_kb: 45732
final_rank: 10

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <tuple>
#define mkp make_pair
#define mkt make_tuple
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
const ll MOD=998244353;
template<class T> void chmin(T &a,const T &b){if(a>b) a=b;}
template<class T> void chmax(T &a,const T &b){if(a<b) a=b;}

ll mod_pow(ll x,ll n){
  x%=MOD;
  ll res=1;
  while(n>0){
    if(n&1) res=res*x%MOD;
    x=x*x%MOD;
    n>>=1;
  }
  return res;
}

ll mod_inverse(ll x){
  return mod_pow(x,MOD-2);
}

void add(ll &a,ll b){
  a=(a+b)%MOD;
}

void mul(ll &a,ll b){
  a%=MOD;b%=MOD;
  a=a*b%MOD;
}

//const ll MOD=998244353; // MOD == 119*2^23+1
//depends on mod_pow,mod_inverse

ll root[24],invroot[24];

void NTT_init(){
    for(int i=0;i<24;++i){
        root[i]=mod_pow(3,(MOD-1)/(1<<i));
        invroot[i]=mod_inverse(root[i]);
    }
}

vector<ll> NTT(vector<ll> a,bool inverse=false){
    int n=a.size();
    int high=0;
    for(int i=0;(1<<i)<n;++i) high++;

    for(int i=0;i<n;++i){
        int mask=0;
        for(int k=0;k<high;++k){
            if(i>>k&1) mask|=(1<<(high-1-k));
        }
        if(i<mask) swap(a[i],a[mask]);
    }

    for(int j=1;(1<<j)<=n;++j){
        int m=(1<<j);
        ll zeta=root[j];
        if(inverse) zeta=invroot[j];
        for(int i=0;i<n;i+=m){
            ll powzeta=1;
            for(int k=i;k<i+m/2;++k){
                ll s=a[k];
                ll t=a[k+m/2]*powzeta%MOD;

                a[k]=(s+t)%MOD;
                a[k+m/2]=(s-t+MOD)%MOD;
                powzeta=powzeta*zeta%MOD;
            }
        }
    }

    if(inverse){
        ll invn=mod_inverse(n);
        for(int i=0;i<n;++i) a[i]=a[i]*invn%MOD;
    }
    return a;
}

vector<ll> convolute(const vector<ll> &a,const vector<ll> &b){
    int size=a.size()+b.size()-1;
    int n=1;
    while(n<size) n<<=1;

    vector<ll> A(n,0),B(n,0);
    for(int i=0;i<a.size();i++) A[i]=a[i];
    for(int i=0;i<b.size();i++) B[i]=b[i];

    A=NTT(A);
    B=NTT(B);

    for(int i=0;i<n;++i) A[i]=A[i]*B[i]%MOD;
    A=NTT(A,true);

    A.resize(size);
    return A;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N;
  ll L;
  cin>>N>>L;
  vector<ll> T(N);
  rep(i,N) cin>>T[i];
  int M;
  ll D;
  cin>>M>>D;
  vector<ll> X(M+1),P(M+1);
  rep(i,M) cin>>X[i]>>P[i];
  X[M]=L;

  NTT_init();

  ll inv100=mod_inverse(100);
  vector<vector<ll>> B(M);
  rep(i,M){
      int diff=X[i+1]-X[i];
      B[i].resize(diff+1,0);
      B[i][0]=P[i]*inv100%MOD;
      B[i][diff]=(100-P[i])*inv100%MOD;
  }

  priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> PQ;
  rep(i,M) PQ.push(mkp(B[i].size(),i));
  while(PQ.size()>1){
      auto f=PQ.top();
      PQ.pop();
      auto s=PQ.top();
      PQ.pop();

      int ft=f.second;
      int st=s.second;
      B[ft]=convolute(B[ft],B[st]);
      B[st].clear();

      PQ.push(mkp(B[ft].size(),ft));
  }

  auto f=PQ.top();PQ.pop();
  vector<ll> dist=B[f.second];
  vector<ll> revd=dist;
  reverse(all(revd));
  dist=convolute(dist,revd);

  int V=dist.size();
  vector<ll> rsum(V+1,0);
  for(int i=V-1;i>=0;i--) rsum[i]=(rsum[i+1]+dist[i])%MOD;

  ll ans=0;
  for(int i=1;i<N;i++){
      ll border=L*(T[0]-T[i])/(2*D);
      if(T[0]-T[i]<0&&(L*abs(T[0]-T[i]))%(2*D)) --border;
      if(border+L>V) continue;
      ans+=rsum[max(0ll,border+L)];
      ans=(ans+MOD)%MOD;
  }
  ans=(N-ans+MOD)%MOD;
  cout<<ans<<endl;


  return 0;
}
accuracy: 0.075
time_ms: 600
memory_kb: 45444
final_rank: 20

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <tuple>
#define mkp make_pair
#define mkt make_tuple
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
const ll MOD=998244353;
template<class T> void chmin(T &a,const T &b){if(a>b) a=b;}
template<class T> void chmax(T &a,const T &b){if(a<b) a=b;}

ll mod_pow(ll x,ll n){
  x%=MOD;
  ll res=1;
  while(n>0){
    if(n&1) res=res*x%MOD;
    x=x*x%MOD;
    n>>=1;
  }
  return res;
}

ll mod_inverse(ll x){
  return mod_pow(x,MOD-2);
}

void add(ll &a,ll b){
  a=(a+b)%MOD;
}

void mul(ll &a,ll b){
  a%=MOD;b%=MOD;
  a=a*b%MOD;
}

//const ll MOD=998244353; // MOD == 119*2^23+1
//depends on mod_pow,mod_inverse

ll root[24],invroot[24];

void NTT_init(){
    for(int i=0;i<24;++i){
        root[i]=mod_pow(3,(MOD-1)/(1<<i));
        invroot[i]=mod_inverse(root[i]);
    }
}

vector<ll> NTT(vector<ll> a,bool inverse=false){
    int n=a.size();
    int high=0;
    for(int i=0;(1<<i)<n;++i) high++;

    for(int i=0;i<n;++i){
        int mask=0;
        for(int k=0;k<high;++k){
            if(i>>k&1) mask|=(1<<(high-1-k));
        }
        if(i<mask) swap(a[i],a[mask]);
    }

    for(int j=1;(1<<j)<=n;++j){
        int m=(1<<j);
        ll zeta=root[j];
        if(inverse) zeta=invroot[j];
        for(int i=0;i<n;i+=m){
            ll powzeta=1;
            for(int k=i;k<i+m/2;++k){
                ll s=a[k];
                ll t=a[k+m/2]*powzeta%MOD;

                a[k]=(s+t)%MOD;
                a[k+m/2]=(s-t+MOD)%MOD;
                powzeta=powzeta*zeta%MOD;
            }
        }
    }

    if(inverse){
        ll invn=mod_inverse(n);
        for(int i=0;i<n;++i) a[i]=a[i]*invn%MOD;
    }
    return a;
}

vector<ll> convolute(const vector<ll> &a,const vector<ll> &b){
    int size=a.size()+b.size()-1;
    int n=1;
    while(n<size) n<<=1;

    vector<ll> A(n,0),B(n,0);
    for(int i=0;i<a.size();i++) A[i]=a[i];
    for(int i=0;i<b.size();i++) B[i]=b[i];

    A=NTT(A);
    B=NTT(B);

    for(int i=0;i<n;++i) A[i]=A[i]*B[i]%MOD;
    A=NTT(A,true);

    A.resize(size);
    return A;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N;
  ll L;
  cin>>N>>L;
  vector<ll> T(N);
  rep(i,N) cin>>T[i];
  int M;
  ll D;
  cin>>M>>D;
  vector<ll> X(M+1),P(M+1);
  rep(i,M) cin>>X[i]>>P[i];
  X[M]=L;

  NTT_init();

  ll inv100=mod_inverse(100);
  vector<vector<ll>> B(M);
  rep(i,M){
      int diff=X[i+1]-X[i];
      B[i].resize(diff+1,0);
      B[i][0]=P[i]*inv100%MOD;
      B[i][diff]=(100-P[i])*inv100%MOD;
  }

  priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> PQ;
  rep(i,M) PQ.push(mkp(B[i].size(),i));
  while(PQ.size()>1){
      auto f=PQ.top();
      PQ.pop();
      auto s=PQ.top();
      PQ.pop();

      int ft=f.second;
      int st=s.second;
      B[ft]=convolute(B[ft],B[st]);
      B[st].clear();

      PQ.push(mkp(B[ft].size(),ft));
  }

  auto f=PQ.top();PQ.pop();
  vector<ll> dist=B[f.second];
  vector<ll> revd=dist;
  reverse(all(revd));
  dist=convolute(dist,revd);

  int V=dist.size();
  vector<ll> rsum(V+1,0);
  for(int i=V-1;i>=0;i--) rsum[i]=rsum[i+1]+dist[i];

  ll ans=0;
  for(int i=1;i<N;i++){
      ll border=L*(T[0]-T[i])/(2*D);
      if(T[0]-T[i]<0&&(L*abs(T[0]-T[i]))%(2*D)) --border;
      if(border+L>V) continue;
      ans+=rsum[max(0ll,border+L)];
      ans=(ans+MOD)%MOD;
  }
  ans=(N-ans+MOD)%MOD;
  cout<<ans<<endl;


  return 0;
}
accuracy: 0.075
time_ms: 570
memory_kb: 45464
final_rank: 19

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <tuple>
#define mkp make_pair
#define mkt make_tuple
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
const ll MOD=998244353;
template<class T> void chmin(T &a,const T &b){if(a>b) a=b;}
template<class T> void chmax(T &a,const T &b){if(a<b) a=b;}

ll mod_pow(ll x,ll n){
  x%=MOD;
  ll res=1;
  while(n>0){
    if(n&1) res=res*x%MOD;
    x=x*x%MOD;
    n>>=1;
  }
  return res;
}

ll mod_inverse(ll x){
  return mod_pow(x,MOD-2);
}

void add(ll &a,ll b){
  a=(a+b)%MOD;
}

void mul(ll &a,ll b){
  a%=MOD;b%=MOD;
  a=a*b%MOD;
}

//const ll MOD=998244353; // MOD == 119*2^23+1
//depends on mod_pow,mod_inverse

ll root[24],invroot[24];

void NTT_init(){
    for(int i=0;i<24;++i){
        root[i]=mod_pow(3,(MOD-1)/(1<<i));
        invroot[i]=mod_inverse(root[i]);
    }
}

vector<ll> NTT(vector<ll> a,bool inverse=false){
    int n=a.size();
    int high=0;
    for(int i=0;(1<<i)<n;++i) high++;

    for(int i=0;i<n;++i){
        int mask=0;
        for(int k=0;k<high;++k){
            if(i>>k&1) mask|=(1<<(high-1-k));
        }
        if(i<mask) swap(a[i],a[mask]);
    }

    for(int j=1;(1<<j)<=n;++j){
        int m=(1<<j);
        ll zeta=root[j];
        if(inverse) zeta=invroot[j];
        for(int i=0;i<n;i+=m){
            ll powzeta=1;
            for(int k=i;k<i+m/2;++k){
                ll s=a[k];
                ll t=a[k+m/2]*powzeta%MOD;

                a[k]=(s+t)%MOD;
                a[k+m/2]=(s-t+MOD)%MOD;
                powzeta=powzeta*zeta%MOD;
            }
        }
    }

    if(inverse){
        ll invn=mod_inverse(n);
        for(int i=0;i<n;++i) a[i]=a[i]*invn%MOD;
    }
    return a;
}

vector<ll> convolute(const vector<ll> &a,const vector<ll> &b){
    int size=a.size()+b.size()-1;
    int n=1;
    while(n<size) n<<=1;

    vector<ll> A(n,0),B(n,0);
    for(int i=0;i<a.size();i++) A[i]=a[i];
    for(int i=0;i<b.size();i++) B[i]=b[i];

    A=NTT(A);
    B=NTT(B);

    for(int i=0;i<n;++i) A[i]=A[i]*B[i]%MOD;
    A=NTT(A,true);

    A.resize(size);
    return A;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N;
  ll L;
  cin>>N>>L;
  vector<ll> T(N);
  rep(i,N) cin>>T[i];
  int M;
  ll D;
  cin>>M>>D;
  vector<ll> X(M+1),P(M+1);
  rep(i,M) cin>>X[i]>>P[i];
  X[M]=L;

  NTT_init();

  ll inv100=mod_inverse(100);
  vector<vector<ll>> B(M);
  rep(i,M){
      int diff=X[i+1]-X[i];
      B[i].resize(diff+1,0);
      B[i][0]=P[i]*inv100%MOD;
      B[i][diff]=(100-P[i])*inv100%MOD;
  }

  priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> PQ;
  rep(i,M) PQ.push(mkp(B[i].size(),i));
  while(PQ.size()>1){
      auto f=PQ.top();
      PQ.pop();
      auto s=PQ.top();
      PQ.pop();

      int ft=f.second;
      int st=s.second;
      B[ft]=convolute(B[ft],B[st]);
      B[st].clear();

      PQ.push(mkp(B[ft].size(),ft));
  }

  auto f=PQ.top();PQ.pop();
  vector<ll> dist=B[f.second];
  vector<ll> revd=dist;
  reverse(all(revd));
  dist=convolute(dist,revd);

  int V=dist.size();
  vector<ll> rsum(V+1,0);
  for(int i=V-1;i>=0;i--) rsum[i]=rsum[i+1]+dist[i];

  ll ans=0;
  for(int i=1;i<N;i++){
      ll border=L*(T[0]-T[i])/(2*D);
      if(T[0]-T[i]<0&&(L*abs(T[0]-T[i]))%(2*D)) --border;
      if(border+L<0||border+L>V) continue;
      ans+=rsum[border+L];
      ans=(ans+MOD)%MOD;
  }
  ans=(N-ans+MOD)%MOD;
  cout<<ans<<endl;


  return 0;
}
accuracy: 0.075
time_ms: 530
memory_kb: 45696
final_rank: 18

code_snippet: #include <iostream>
#include <algorithm>
#include <string>
#include <vector>
#include <cmath>
#include <map>
#include <queue>
#include <iomanip>
#include <set>
#include <tuple>
#define mkp make_pair
#define mkt make_tuple
#define rep(i,n) for(int i = 0; i < (n); ++i)
#define all(v) v.begin(),v.end()
using namespace std;
typedef long long ll;
const ll MOD=998244353;
template<class T> void chmin(T &a,const T &b){if(a>b) a=b;}
template<class T> void chmax(T &a,const T &b){if(a<b) a=b;}

ll mod_pow(ll x,ll n){
  x%=MOD;
  ll res=1;
  while(n>0){
    if(n&1) res=res*x%MOD;
    x=x*x%MOD;
    n>>=1;
  }
  return res;
}

ll mod_inverse(ll x){
  return mod_pow(x,MOD-2);
}

void add(ll &a,ll b){
  a=(a+b)%MOD;
}

void mul(ll &a,ll b){
  a%=MOD;b%=MOD;
  a=a*b%MOD;
}

//const ll MOD=998244353; // MOD == 119*2^23+1
//depends on mod_pow,mod_inverse

ll root[24],invroot[24];

void NTT_init(){
    for(int i=0;i<24;++i){
        root[i]=mod_pow(3,(MOD-1)/(1<<i));
        invroot[i]=mod_inverse(root[i]);
    }
}

vector<ll> NTT(vector<ll> a,bool inverse=false){
    int n=a.size();
    int high=0;
    for(int i=0;(1<<i)<n;++i) high++;

    for(int i=0;i<n;++i){
        int mask=0;
        for(int k=0;k<high;++k){
            if(i>>k&1) mask|=(1<<(high-1-k));
        }
        if(i<mask) swap(a[i],a[mask]);
    }

    for(int j=1;(1<<j)<=n;++j){
        int m=(1<<j);
        ll zeta=root[j];
        if(inverse) zeta=invroot[j];
        for(int i=0;i<n;i+=m){
            ll powzeta=1;
            for(int k=i;k<i+m/2;++k){
                ll s=a[k];
                ll t=a[k+m/2]*powzeta%MOD;

                a[k]=(s+t)%MOD;
                a[k+m/2]=(s-t+MOD)%MOD;
                powzeta=powzeta*zeta%MOD;
            }
        }
    }

    if(inverse){
        ll invn=mod_inverse(n);
        for(int i=0;i<n;++i) a[i]=a[i]*invn%MOD;
    }
    return a;
}

vector<ll> convolute(const vector<ll> &a,const vector<ll> &b){
    int size=a.size()+b.size()-1;
    int n=1;
    while(n<size) n<<=1;

    vector<ll> A(n,0),B(n,0);
    for(int i=0;i<a.size();i++) A[i]=a[i];
    for(int i=0;i<b.size();i++) B[i]=b[i];

    A=NTT(A);
    B=NTT(B);

    for(int i=0;i<n;++i) A[i]=A[i]*B[i]%MOD;
    A=NTT(A,true);

    A.resize(size);
    return A;
}

int main(){
  cin.tie(0);
  ios::sync_with_stdio(false);

  int N;
  ll L;
  cin>>N>>L;
  vector<ll> T(N);
  rep(i,N) cin>>T[i];
  int M;
  ll D;
  cin>>M>>D;
  vector<ll> X(M+1),P(M+1);
  rep(i,M) cin>>X[i]>>P[i];
  X[M]=L;

  NTT_init();

  ll inv100=mod_inverse(100);
  vector<vector<ll>> B(M);
  rep(i,M){
      int diff=X[i+1]-X[i];
      B[i].resize(diff+1,0);
      B[i][0]=P[i]*inv100%MOD;
      B[i][diff]=(100-P[i])*inv100%MOD;
  }

  priority_queue<pair<int,int>,vector<pair<int,int>>,greater<pair<int,int>>> PQ;
  rep(i,M) PQ.push(mkp(B[i].size(),i));
  while(PQ.size()>1){
      auto f=PQ.top();
      PQ.pop();
      auto s=PQ.top();
      PQ.pop();

      int ft=f.second;
      int st=s.second;
      B[ft]=convolute(B[ft],B[st]);
      B[st].clear();

      PQ.push(mkp(B[ft].size(),ft));
  }

  auto f=PQ.top();PQ.pop();
  vector<ll> dist=B[f.second];
  vector<ll> revd=dist;
  reverse(all(revd));
  dist=convolute(dist,revd);

  int V=dist.size();
  vector<ll> rsum(V+1,0);
  for(int i=V-1;i>=0;i--) rsum[i]=rsum[i+1]+dist[i];

  ll ans=0;
  for(int i=1;i<N;i++){
      ll border=L*(T[0]-T[i])/(2*D);
      if(T[0]-T[i]<0&&(L*abs(T[0]-T[i]))%(2*D)) --border;
      ans+=rsum[min((ll)V,border+L)];
      ans=(ans+MOD)%MOD;
  }
  ans=(N-ans+MOD)%MOD;
  cout<<ans<<endl;


  return 0;
}
accuracy: 0.075
time_ms: 460
memory_kb: 45924
final_rank: 17