#include <iostream>
#include <vector>
using namespace std;
const long long MOD = 1000000007;
const long long CUTOFF = 1000000006;
// Szybkie potęgowanie modularne
long long power(long long base, long long exp) {
long long res = 1;
base %= MOD;
while (exp > 0) {
if (exp % 2 == 1) res = (res * base) % MOD;
base = (base * base) % MOD;
exp /= 2;
}
return res;
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
int n, q;
if (!(cin >> n >> q)) return 0;
vector<long long> a(n + 1);
vector<long long> b(n + 1);
for (int i = 1; i <= n; ++i) {
cin >> a[i] >> b[i];
}
// Tablica przeskoków do najbliższego wydarzenia nadającego pozytywny dodatek
vector<int> next_pos_a(n + 2);
next_pos_a[n + 1] = n + 1;
for (int i = n; i >= 1; --i) {
if (a[i] > 0) next_pos_a[i] = i;
else next_pos_a[i] = next_pos_a[i + 1];
}
// Tablica przeskoków do najbliższego wydarzenia mogącego podwajać bazę (b > 1)
vector<int> next_b_gt_1(n + 2);
next_b_gt_1[n + 1] = n + 1;
for (int i = n; i >= 1; --i) {
if (b[i] > 1) next_b_gt_1[i] = i;
else next_b_gt_1[i] = next_b_gt_1[i + 1];
}
// Sumy prefiksowe wartości 'a'
vector<long long> prefix_a(n + 1, 0);
for (int i = 1; i <= n; ++i) {
prefix_a[i] = prefix_a[i - 1] + a[i];
}
// Prekalkulacja złożeń transformacji liniowych F(x) = C*x + D w module
vector<long long> C(n + 1, 1);
vector<long long> D(n + 1, 0);
vector<long long> invC(n + 1, 1);
for (int i = 1; i <= n; ++i) {
long long c_i = (b[i] == 1) ? 1 : (b[i] % MOD);
long long d_i = (b[i] == 1) ? (a[i] % MOD) : 0;
C[i] = (C[i - 1] * c_i) % MOD;
D[i] = (D[i - 1] * c_i + d_i) % MOD;
}
// Odwrotności modularne C liczone optymalnie od tyłu by uniknąć 500,000 logarytmicznych operacji
invC[n] = power(C[n], MOD - 2);
for (int i = n - 1; i >= 0; --i) {
long long c_next = (b[i + 1] == 1) ? 1 : (b[i + 1] % MOD);
invC[i] = (invC[i + 1] * c_next) % MOD;
}
// Odpowiadanie na zapytania
for (int query = 0; query < q; ++query) {
long long x;
int l, r;
cin >> x >> l >> r;
long long x_val = x;
int curr = l + 1;
if (x_val == 0) {
int k = next_pos_a[curr];
if (k > r) {
cout << 0 << "\n";
continue;
}
x_val = a[k];
curr = k + 1;
}
while (x_val <= CUTOFF && curr <= r) {
int k = next_b_gt_1[curr];
if (k > r) {
x_val += prefix_a[r] - prefix_a[curr - 1];
curr = r + 1;
break;
}
// Aplikowanie wszystkich b_m = 1 w bloku przed k
x_val += prefix_a[k - 1] - prefix_a[curr - 1];
if (x_val > CUTOFF) {
curr = k;
break;
}
long long threshold = a[k] / (b[k] - 1);
if (x_val <= threshold) x_val += a[k];
else x_val *= b[k];
curr = k + 1;
}
// Gdy x_val przekroczy bezpieczną granicę zdefiniowanego progu - wykonujemy szybkie złożenie w czasie O(1)
if (curr <= r) {
x_val %= MOD;
long long C_range = (C[r] * invC[curr - 1]) % MOD;
long long D_range = (D[r] - C_range * D[curr - 1]) % MOD;
if (D_range < 0) D_range = (D_range % MOD + MOD) % MOD;
x_val = (C_range * x_val + D_range) % MOD;
} else {
x_val %= MOD;
}
cout << x_val << "\n";
}
return 0;
}
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 | #include <iostream> #include <vector> using namespace std; const long long MOD = 1000000007; const long long CUTOFF = 1000000006; // Szybkie potęgowanie modularne long long power(long long base, long long exp) { long long res = 1; base %= MOD; while (exp > 0) { if (exp % 2 == 1) res = (res * base) % MOD; base = (base * base) % MOD; exp /= 2; } return res; } int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); int n, q; if (!(cin >> n >> q)) return 0; vector<long long> a(n + 1); vector<long long> b(n + 1); for (int i = 1; i <= n; ++i) { cin >> a[i] >> b[i]; } // Tablica przeskoków do najbliższego wydarzenia nadającego pozytywny dodatek vector<int> next_pos_a(n + 2); next_pos_a[n + 1] = n + 1; for (int i = n; i >= 1; --i) { if (a[i] > 0) next_pos_a[i] = i; else next_pos_a[i] = next_pos_a[i + 1]; } // Tablica przeskoków do najbliższego wydarzenia mogącego podwajać bazę (b > 1) vector<int> next_b_gt_1(n + 2); next_b_gt_1[n + 1] = n + 1; for (int i = n; i >= 1; --i) { if (b[i] > 1) next_b_gt_1[i] = i; else next_b_gt_1[i] = next_b_gt_1[i + 1]; } // Sumy prefiksowe wartości 'a' vector<long long> prefix_a(n + 1, 0); for (int i = 1; i <= n; ++i) { prefix_a[i] = prefix_a[i - 1] + a[i]; } // Prekalkulacja złożeń transformacji liniowych F(x) = C*x + D w module vector<long long> C(n + 1, 1); vector<long long> D(n + 1, 0); vector<long long> invC(n + 1, 1); for (int i = 1; i <= n; ++i) { long long c_i = (b[i] == 1) ? 1 : (b[i] % MOD); long long d_i = (b[i] == 1) ? (a[i] % MOD) : 0; C[i] = (C[i - 1] * c_i) % MOD; D[i] = (D[i - 1] * c_i + d_i) % MOD; } // Odwrotności modularne C liczone optymalnie od tyłu by uniknąć 500,000 logarytmicznych operacji invC[n] = power(C[n], MOD - 2); for (int i = n - 1; i >= 0; --i) { long long c_next = (b[i + 1] == 1) ? 1 : (b[i + 1] % MOD); invC[i] = (invC[i + 1] * c_next) % MOD; } // Odpowiadanie na zapytania for (int query = 0; query < q; ++query) { long long x; int l, r; cin >> x >> l >> r; long long x_val = x; int curr = l + 1; if (x_val == 0) { int k = next_pos_a[curr]; if (k > r) { cout << 0 << "\n"; continue; } x_val = a[k]; curr = k + 1; } while (x_val <= CUTOFF && curr <= r) { int k = next_b_gt_1[curr]; if (k > r) { x_val += prefix_a[r] - prefix_a[curr - 1]; curr = r + 1; break; } // Aplikowanie wszystkich b_m = 1 w bloku przed k x_val += prefix_a[k - 1] - prefix_a[curr - 1]; if (x_val > CUTOFF) { curr = k; break; } long long threshold = a[k] / (b[k] - 1); if (x_val <= threshold) x_val += a[k]; else x_val *= b[k]; curr = k + 1; } // Gdy x_val przekroczy bezpieczną granicę zdefiniowanego progu - wykonujemy szybkie złożenie w czasie O(1) if (curr <= r) { x_val %= MOD; long long C_range = (C[r] * invC[curr - 1]) % MOD; long long D_range = (D[r] - C_range * D[curr - 1]) % MOD; if (D_range < 0) D_range = (D_range % MOD + MOD) % MOD; x_val = (C_range * x_val + D_range) % MOD; } else { x_val %= MOD; } cout << x_val << "\n"; } return 0; } |
English