#include #include using namespace std; using ll = long long; // [1e18, 5e18] からランダムな素数を取ってくる // ミラーラビンとか使えば実行時にランダムに出来るのでハックありでも対応可能 // https://www.wolframalpha.com/input?i=RandomPrime%5B%7B10%5E18%2C+5*10%5E18%7D%5D const ll MOD = 4554013204529924683; static_assert(MOD < numeric_limits::max() / 2); using S = ll; S op(const S a, const S b) { return (a + b) % MOD; } S e() { return 0; } using segtree = atcoder::segtree; int main() { ll n, q, k; cin >> n >> q >> k; vector a(n); for (auto& x : a) { cin >> x; // 今後 % MOD の値しか使わないので、正の数にしておく x = (x + MOD) % MOD; } // b[i] := (a[i] * pow(k, i)) % MOD vector b(n); __uint128_t powk = 1; for (int i = 0; i < n; i++) { // a[i], powk ともに MOD < 2^63 以下なので、128ビットで十分 b[i] = (a[i] * powk) % MOD; powk *= k; powk %= MOD; } segtree st(b); for (int i = 0; i < q; i++) { int l, r; cin >> l >> r; l--; r--; // S = Σ_{i=l}^r (a_i k^{i-l}) として、 // S = 0 かどうかを、S % MOD = 0 かどうかで判定する。 // この方法で高い確率で正解できる。 // // 判定が誤るのは S ≡ 0 かつ S > 0 のとき、すなわち S が MOD を素因数として含むとき。 // しかしながら MOD として取りうる値は 10^16個ぐらいあり、 // ( https://ja.wikipedia.org/wiki/素数定理 の π(10^18) あたりを参照) // S は高々 r-l <= 10^5 個程度しか 10^18 以上の素因数を含まないので、その確率は非常に低い。 cout << (st.prod(l, r + 1) ? "Yes" : "No") << endl; } }