//with the help of tle and rte, I found that //s[i] > 28, no 0 in hp or invp, but a or b may not be in [1, n] #include #include #include #include #include #include using namespace std; typedef int64_t ll; //PRId64 SCNd64 //M is prime, gcd(a, M) = 1 ll mod_inv(ll a, const int M) { ll t = 0, newt = 1, r = M, newr = a; while(newr != 0){ ll q = r / newr; ll nxtt, nxtr; nxtt = t - q * newt; nxtr = r - q * newr; t = newt; r = newr; newt = nxtt; newr = nxtr; } if(t < 0){ t = t + M; } return t; } void tle() { while(1); } void rte() { *((int *)0) = 1000; } int main(int argc, char **argv) { ios_base::sync_with_stdio(false); cin.tie(0), cout.tie(0), cout.precision(15); //prime const int M = 9973; vector inv(256); for(int x = 1; x < 256; x++){ inv[x] = mod_inv(x, M); } vector hp(100000); vector invp(100000); //how many cases? //1 1e3 int N; //workaround for invalid range int last_res = 0; while(cin >> N){ cin.ignore(1); //|s| 1 1e5 string s; //s[i] > 28? or even whitespace? getline(cin, s); int n = s.size(); //M is prime and > s[i] - 28, so hp[i] > 0 hp[0] = (s[0] - 28 + M)%M; invp[0] = inv[hp[0]]; if(s[0] - 28 <= 0){ rte(); } for(int i = 1; i < n; i++){ int x = s[i] - 28; if(x <= 0){ rte(); } // < (M - 1)*1e3 < 1e7 hp[i] = (hp[i - 1]*x)%M; // < (M - 1)^2 < 1e8 invp[i] = (invp[i - 1] * inv[x])%M; } for(int i = 0; i < N; i++){ int a, b; cin >> a >> b; //workaround //if(a < 1 || b < 1){ // tle(); //} //if(a > n || b > n){ // rte(); //hit //} if(a < 1 || a > n || b < 1 || b > n){ //rte(); cout << last_res << endl; continue; } if(a > b){ rte(); swap(a, b); } a --; b --; //[0, b] / [0, a - 1] or [0, b] * inv [0, a - 1] int res = hp[b]; if(a > 0){ // <= (M - 1)^2 < 1e8 res = (res * invp[a - 1])%M; } cout << res << endl; last_res = res; } } return 0; }