#include<iostream>
#include<cstring>
#include<vector>
#include<cassert>
#include<algorithm>
#include<cmath>
#include<stdint.h>
#include<array>
using namespace std;
using LL = long long;
template<const int T>
struct ModInt {
const static int mod = T;
int x;
ModInt(int x = 0) : x(x % mod) {}
ModInt(long long x) : x(int(x % mod)) {}
int val() { return x; }
ModInt operator + (const ModInt &a) const { int x0 = x + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
ModInt operator - (const ModInt &a) const { int x0 = x - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
ModInt operator * (const ModInt &a) const { return ModInt(1LL * x * a.x % mod); }
ModInt operator / (const ModInt &a) const { return *this * a.inv(); }
bool operator == (const ModInt &a) const { return x == a.x; };
bool operator != (const ModInt &a) const { return x != a.x; };
void operator += (const ModInt &a) { x += a.x; if (x >= mod) x -= mod; }
void operator -= (const ModInt &a) { x -= a.x; if (x < 0) x += mod; }
void operator *= (const ModInt &a) { x = 1LL * x * a.x % mod; }
void operator /= (const ModInt &a) { *this = *this / a; }
friend ModInt operator + (int y, const ModInt &a){ int x0 = y + a.x; return ModInt(x0 < mod ? x0 : x0 - mod); }
friend ModInt operator - (int y, const ModInt &a){ int x0 = y - a.x; return ModInt(x0 < 0 ? x0 + mod : x0); }
friend ModInt operator * (int y, const ModInt &a){ return ModInt(1LL * y * a.x % mod);}
friend ModInt operator / (int y, const ModInt &a){ return ModInt(y) / a;}
friend ostream &operator<<(ostream &os, const ModInt &a) { return os << a.x;}
friend istream &operator>>(istream &is, ModInt &t){return is >> t.x;}
ModInt pow(int64_t n) const {
ModInt res(1), mul(x);
while(n){
if (n & 1) res *= mul;
mul *= mul;
n >>= 1;
}
return res;
}
ModInt inv() const {
int a = x, b = mod, u = 1, v = 0;
while (b) {
int t = a / b;
a -= t * b; swap(a, b);
u -= t * v; swap(u, v);
}
if (u < 0) u += mod;
return u;
}
};
using mint = ModInt<1000000007>;
namespace FastFourierTransform {
using real = double;
struct C {
real x, y;
C() : x(0), y(0) {}
C(real x, real y) : x(x), y(y) {}
inline C operator+(const C &c) const { return C(x + c.x, y + c.y); }
inline C operator-(const C &c) const { return C(x - c.x, y - c.y); }
inline C operator*(const C &c) const { return C(x * c.x - y * c.y, x * c.y + y * c.x); }
inline C conj() const { return C(x, -y); }
};
const real PI = acosl(-1);
int base = 1;
vector< C > rts = { {0, 0},
{1, 0} };
vector< int > rev = {0, 1};
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));
}
while(base < nbase) {
real angle = PI * 2.0 / (1 << (base + 1));
for(int i = 1 << (base - 1); i < (1 << base); i++) {
rts[i << 1] = rts[i];
real angle_i = angle * (2 * i + 1 - (1 << base));
rts[(i << 1) + 1] = C(cos(angle_i), sin(angle_i));
}
++base;
}
}
void fft(vector< C > &a, int n) {
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++) {
C z = a[i + j + k] * rts[j + k];
a[i + j + k] = a[i + j] - z;
a[i + j] = a[i + j] + z;
}
}
}
}
vector< int64_t > multiply(const vector< int > &a, const vector< int > &b) {
int need = (int) a.size() + (int) b.size() - 1;
int nbase = 1;
while((1 << nbase) < need) nbase++;
ensure_base(nbase);
int sz = 1 << nbase;
vector< C > fa(sz);
for(int i = 0; i < sz; i++) {
int x = (i < (int) a.size() ? a[i] : 0);
int y = (i < (int) b.size() ? b[i] : 0);
fa[i] = C(x, y);
}
fft(fa, sz);
C r(0, -0.25 / (sz >> 1)), s(0, 1), t(0.5, 0);
for(int i = 0; i <= (sz >> 1); i++) {
int j = (sz - i) & (sz - 1);
C z = (fa[j] * fa[j] - (fa[i] * fa[i]).conj()) * r;
fa[j] = (fa[i] * fa[i] - (fa[j] * fa[j]).conj()) * r;
fa[i] = z;
}
for(int i = 0; i < (sz >> 1); i++) {
C A0 = (fa[i] + fa[i + (sz >> 1)]) * t;
C A1 = (fa[i] - fa[i + (sz >> 1)]) * t * rts[(sz >> 1) + i];
fa[i] = A0 + A1 * s;
}
fft(fa, sz >> 1);
vector< int64_t > ret(need);
for(int i = 0; i < need; i++) {
ret[i] = llround(i & 1 ? fa[i >> 1].y : fa[i >> 1].x);
}
return ret;
}
};
template< typename T >
struct ArbitraryModConvolution {
using real = FastFourierTransform::real;
using C = FastFourierTransform::C;
ArbitraryModConvolution() = default;
static vector< T > multiply(const vector< T > &a, const vector< T > &b, int need = -1) {
if(need == -1) need = a.size() + b.size() - 1;
int nbase = 0;
while((1 << nbase) < need) nbase++;
FastFourierTransform::ensure_base(nbase);
int sz = 1 << nbase;
vector< C > fa(sz);
for(int i = 0; i < a.size(); i++) {
fa[i] = C(a[i].x & ((1 << 15) - 1), a[i].x >> 15);
}
fft(fa, sz);
vector< C > fb(sz);
if(a == b) {
fb = fa;
} else {
for(int i = 0; i < b.size(); i++) {
fb[i] = C(b[i].x & ((1 << 15) - 1), b[i].x >> 15);
}
fft(fb, sz);
}
real ratio = 0.25 / sz;
C r2(0, -1), r3(ratio, 0), r4(0, -ratio), r5(0, 1);
for(int i = 0; i <= (sz >> 1); i++) {
int j = (sz - i) & (sz - 1);
C a1 = (fa[i] + fa[j].conj());
C a2 = (fa[i] - fa[j].conj()) * r2;
C b1 = (fb[i] + fb[j].conj()) * r3;
C b2 = (fb[i] - fb[j].conj()) * r4;
if(i != j) {
C c1 = (fa[j] + fa[i].conj());
C c2 = (fa[j] - fa[i].conj()) * r2;
C d1 = (fb[j] + fb[i].conj()) * r3;
C d2 = (fb[j] - fb[i].conj()) * r4;
fa[i] = c1 * d1 + c2 * d2 * r5;
fb[i] = c1 * d2 + c2 * d1;
}
fa[j] = a1 * b1 + a2 * b2 * r5;
fb[j] = a1 * b2 + a2 * b1;
}
fft(fa, sz);
fft(fb, sz);
vector< T > ret(need);
for(int i = 0; i < need; i++) {
int64_t aa = llround(fa[i].x);
int64_t bb = llround(fb[i].x);
int64_t cc = llround(fa[i].y);
aa = T(aa).x, bb = T(bb).x, cc = T(cc).x;
ret[i] = aa + (bb << 15) + (cc << 30);
}
return ret;
}
};
const int maxn = 6e5 + 5;
mint ans[maxn];
int b[205];
vector<mint> p[1505];
int n, m, q;
ArbitraryModConvolution<mint> fft;
vector<array<int, 3> > tr[1505 * 4];
void modify(int u, int l, int r, const array<int, 3> &q){
if (l == r){
tr[u].push_back(q);
return;
}
int mid = (l + r) / 2;
if (q[0] <= mid and q[1] > mid){
tr[u].push_back(q);
return;
}
if (q[1] <= mid) modify(2 * u, l, mid, q);
else modify(2 * u + 1, mid + 1, r, q);
}
vector<mint> dp[1505];
void solve(int u, int l, int r){
if (l == r){
mint sum = 0;
for(int j = 0; j <= m; j++) sum += b[j] * p[r][j];
for(auto [l, r, id] : tr[u]){
ans[id] = sum;
}
return;
}
int mid = (l + r) / 2;
solve(2 * u, l, mid);
solve(2 * u + 1, mid + 1, r);
if (!tr[u].empty()){
dp[mid] = p[mid];
dp[mid + 1] = p[mid + 1];
for(int i = mid - 1; i >= l; i--){
dp[i] = fft.multiply(p[i], dp[i + 1]);
dp[i].resize(m + 1);
}
for(int i = mid + 2; i <= r; i++){
dp[i] = fft.multiply(p[i], dp[i - 1]);
dp[i].resize(m + 1);
}
for(auto [l, r, id] : tr[u]){
auto c = fft.multiply(dp[l], dp[r]);
mint sum = 0;
for(int j = 0; j <= m; j++) sum += b[j] * c[j];
ans[id] = sum;
}
}
}
int main(){
#ifdef LOCAL
freopen("data.in", "r", stdin);
freopen("data.out", "w", stdout);
#endif
cin.tie(0);
cout.tie(0);
ios::sync_with_stdio(0);
cin >> n >> m >> q;
for(int i = 0; i <= m; i++) cin >> b[i];
for(int i = 1; i <= n; i++){
p[i].resize(m + 1);
for(int j = 0; j <= m; j++){
int x;
cin >> x;
p[i][j] = x;
}
}
for(int i = 0; i < q; i++){
int l, r;
cin >> l >> r;
modify(1, 1, n, {l, r, i});
}
solve(1, 1, n);
for(int i = 0; i < q; i++){
cout << ans[i] << '\n';
}
}