#include <bits/stdc++.h>
using namespace std;
#define fwd(i, a, n) for (int i = (a); i < (n); i++)
#define rep(i, n) fwd(i, 0, n)
#define all(X) X.begin(), X.end()
#define sz(X) int(size(X))
#define pb push_back
#define eb emplace_back
#define st first
#define nd second
using pii = pair<int, int>; using vi = vector<int>;
using ll = long long; using ld = long double;
#ifdef LOC
auto SS = signal(6, [](int) { *(int *)0 = 0; });
#define DTP(x, y) auto operator << (auto &o, auto a) -> decltype(y, o) { o << "("; x; return o << ")"; }
DTP(o << a.st << ", " << a.nd, a.nd);
DTP(for (auto i : a) o << i << ", ", all(a));
void dump(auto... x) { (( cerr << x << ", " ), ...) << '\n'; }
#define deb(x...) cerr << setw(4) << __LINE__ << ":[" #x "]: ", dump(x)
#else
#define deb(...) 0
#endif
#define S 500007
ll mod = 1000000007;
ll pot(ll x, ll y) {
if(y == 0)
return 1;
if(y == 1)
return x;
if(y % 2 == 0) {
ll p = pot(x,y/2);
return (p * p) % mod;
}
return (pot(x,y-1) * x) % mod;
}
ll A[S], B[S];
int nextt[S];
int nextt2[S];
ll pref_sum[S];
ll X[S], Y[S];
ll X2[S], Y2[S];
// Prioritize multiplication and use addition only is B[i] = 1
// This means that we can also use it to multiply by everything on range.
ll apply_opt(int l, int r, ll s) {
ll x = 1;
ll y = 0;
if (l != 1) {
if (X2[l-1] == 0) {
X2[l-1] = pot(X[l-1], mod-2);
Y2[l-1] = X2[l-1] * (-Y[l-1]);
Y2[l-1] %= mod;
}
x = X2[l-1];
y = Y2[l-1];
}
x *= X[r];
x %= mod;
y *= X[r];
y += Y[r];
return (s * x + y) % mod;
}
// Bro pls, who created case x = 0?
void solve() {
int n,q;
cin >> n >> q;
X[0] = 1;
for(int i = 1; i <= n; i++) {
cin >> A[i] >> B[i];
pref_sum[i] = pref_sum[i-1] + A[i];
if(B[i] == 1) {
X[i] = X[i-1];
Y[i] = Y[i-1] + A[i];
if (Y[i] >= mod) Y[i] -= mod;
} else {
X[i] = (X[i-1] * B[i]) % mod;
Y[i] = (Y[i-1] * B[i]) % mod;
}
}
nextt[n+1] = n+1;
nextt2[n+1] = n+1;
for (int i = n; i >= 1; i--) {
if(B[i] > 1)
nextt[i] = i;
else
nextt[i] = nextt[i+1];
if (A[i] > 0)
nextt2[i] = i;
else
nextt2[i] = nextt2[i+1];
}
while(q--) {
ll x;
int l,r;
cin >> x >> l >> r;
l++;
if (x == 0) {
if (nextt2[l] > r) {
cout << 0 << "\n";
continue;
}
x = A[nextt2[l]];
l = nextt2[l] + 1;
}
// We look for next mult where we do manual decision until we are bigger than mod
// or we reach end. We finish with one opt.
while (x < mod) {
// apply sum from l to nextt[l] - 1.
// That's why pref sum is not modulo.
if (nextt[l] > r)
break;
x += pref_sum[nextt[l]-1];
x -= pref_sum[l-1];
l = nextt[l];
if (x >= mod)
break;
// what to do
if (x * B[l] > x + A[l])
x *= B[l];
else
x += A[l];
l++;
}
x %= mod;
deb(l, r, x);
// apply the rest
if (l <= r) {
x = apply_opt(l, r, x);
}
if (x < 0)
x += mod;
cout << x << "\n";
}
}
int32_t main() {
cin.tie(0)->sync_with_stdio(0);
cout << fixed << setprecision(10);
solve();
}
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 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 | #include <bits/stdc++.h> using namespace std; #define fwd(i, a, n) for (int i = (a); i < (n); i++) #define rep(i, n) fwd(i, 0, n) #define all(X) X.begin(), X.end() #define sz(X) int(size(X)) #define pb push_back #define eb emplace_back #define st first #define nd second using pii = pair<int, int>; using vi = vector<int>; using ll = long long; using ld = long double; #ifdef LOC auto SS = signal(6, [](int) { *(int *)0 = 0; }); #define DTP(x, y) auto operator << (auto &o, auto a) -> decltype(y, o) { o << "("; x; return o << ")"; } DTP(o << a.st << ", " << a.nd, a.nd); DTP(for (auto i : a) o << i << ", ", all(a)); void dump(auto... x) { (( cerr << x << ", " ), ...) << '\n'; } #define deb(x...) cerr << setw(4) << __LINE__ << ":[" #x "]: ", dump(x) #else #define deb(...) 0 #endif #define S 500007 ll mod = 1000000007; ll pot(ll x, ll y) { if(y == 0) return 1; if(y == 1) return x; if(y % 2 == 0) { ll p = pot(x,y/2); return (p * p) % mod; } return (pot(x,y-1) * x) % mod; } ll A[S], B[S]; int nextt[S]; int nextt2[S]; ll pref_sum[S]; ll X[S], Y[S]; ll X2[S], Y2[S]; // Prioritize multiplication and use addition only is B[i] = 1 // This means that we can also use it to multiply by everything on range. ll apply_opt(int l, int r, ll s) { ll x = 1; ll y = 0; if (l != 1) { if (X2[l-1] == 0) { X2[l-1] = pot(X[l-1], mod-2); Y2[l-1] = X2[l-1] * (-Y[l-1]); Y2[l-1] %= mod; } x = X2[l-1]; y = Y2[l-1]; } x *= X[r]; x %= mod; y *= X[r]; y += Y[r]; return (s * x + y) % mod; } // Bro pls, who created case x = 0? void solve() { int n,q; cin >> n >> q; X[0] = 1; for(int i = 1; i <= n; i++) { cin >> A[i] >> B[i]; pref_sum[i] = pref_sum[i-1] + A[i]; if(B[i] == 1) { X[i] = X[i-1]; Y[i] = Y[i-1] + A[i]; if (Y[i] >= mod) Y[i] -= mod; } else { X[i] = (X[i-1] * B[i]) % mod; Y[i] = (Y[i-1] * B[i]) % mod; } } nextt[n+1] = n+1; nextt2[n+1] = n+1; for (int i = n; i >= 1; i--) { if(B[i] > 1) nextt[i] = i; else nextt[i] = nextt[i+1]; if (A[i] > 0) nextt2[i] = i; else nextt2[i] = nextt2[i+1]; } while(q--) { ll x; int l,r; cin >> x >> l >> r; l++; if (x == 0) { if (nextt2[l] > r) { cout << 0 << "\n"; continue; } x = A[nextt2[l]]; l = nextt2[l] + 1; } // We look for next mult where we do manual decision until we are bigger than mod // or we reach end. We finish with one opt. while (x < mod) { // apply sum from l to nextt[l] - 1. // That's why pref sum is not modulo. if (nextt[l] > r) break; x += pref_sum[nextt[l]-1]; x -= pref_sum[l-1]; l = nextt[l]; if (x >= mod) break; // what to do if (x * B[l] > x + A[l]) x *= B[l]; else x += A[l]; l++; } x %= mod; deb(l, r, x); // apply the rest if (l <= r) { x = apply_opt(l, r, x); } if (x < 0) x += mod; cout << x << "\n"; } } int32_t main() { cin.tie(0)->sync_with_stdio(0); cout << fixed << setprecision(10); solve(); } |
English