Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <iostream>
- #include <fstream>
- #include <algorithm>
- using namespace std;
- const int MOD = 997;
- class arbint
- {
- public:
- arbint(int n, int k)
- {
- this->n = n;
- this->k = k;
- v.resize((1 << (int)ceil(log2(n) + 1)), 1);
- edges.resize(n+1, k*k);
- Build(1, 1, n);
- // for(int i = 1; i < v.size(); ++i)
- // cout << i << " " << v[i] << "\n";
- }
- void AddEdges(int st, int nr)
- {
- edges[st] = k * k + nr;
- Update(1, st, st+1);
- }
- int Query(int st, int dr)
- {
- return Query(1, 1, n, st, dr);
- }
- private:
- void Build(int nod, int st, int dr)
- {
- if(st == dr)
- return;
- if(st + 1 == dr)
- {
- v[nod] = edges[st];
- return;
- }
- int mid = (st + dr) / 2;
- int nodSt = 2 * nod, nodDr = 2 * nod + 1;
- Build(nodSt, st, mid);
- if(mid+1 > n)
- {
- v[nod] = v[nodSt];
- return;
- }
- Build(nodDr, mid+1, dr);
- v[nod] = (v[nodSt] * v[nodDr] * k * k) % MOD;
- }
- void Update(int nod, int st, int dr)
- {
- if(st == dr)
- return;
- if(st + 1 == dr)
- {
- v[nod] = edges[st];
- return;
- }
- int mid = (st + dr) / 2;
- int nodSt = 2 * nod, nodDr = 2 * nod + 1;
- if(nod <= mid)
- Update(nodSt, st, mid);
- else
- Update(nodDr, mid+1, dr);
- v[nod] = (v[nodSt] * v[nodDr] * edges[mid]) % MOD;
- }
- int Query(int nod, int st, int dr, int start, int stop)
- {
- if(start <= st && stop >= dr)
- return v[nod];
- int ret = 1;
- int mid = (st + dr) / 2;
- int nodSt = 2 * nod, nodDr = 2 * nod + 1;
- if(start <= mid)
- ret *= Query(nodSt, st, mid, start, stop);
- if(stop > mid)
- ret *= Query(nodDr, mid+1, dr, start, stop);
- if(start <= mid && stop > mid)
- ret = ret * edges[mid];
- ret %= MOD;
- return ret;
- }
- int n, k;
- vector<int> v;
- vector<int> edges; //nr muchii de la i la i+1
- };
- int main()
- {
- ifstream in("namlei.in");
- ofstream out("namlei.out");
- int n, K, x, y;
- in >> n >> K;
- n++;
- vector<vector<vector<int> > > edges(n+1, vector<vector<int> >(K+1, vector<int>(K+1, 1)));
- arbint arb(n, K);
- in >> x >> y;
- for(int i = 1; i < n; ++i)
- {
- int cnt, j, k;
- in >> cnt >> j >> k;
- arb.AddEdges(i, cnt);
- edges[i][j+1][k+1]++;
- // cout << i << " " << j+1 << " " << k+1 << "\n";
- for(int w = 1; w < cnt; ++w)
- {
- j = (j * x + k * w * y) % K;
- k = (j * w * x + k * y) % K;
- edges[i][j+1][k+1]++;
- // cout << i << " " << j+1 << " " << k+1 << "\n";
- }
- }
- char t;
- while(in >> t)
- {
- if(t == 'U')
- {
- int i, cnt, j, k;
- in >> i >> cnt >> j >> k;
- arb.AddEdges(i, cnt);
- edges[i][j+1][k+1]++;
- for(int w = 1; w < cnt; ++w)
- {
- j = (j * x + k * w * y + 1) % K;
- k = (j * w * x + k * y + 1) % K;
- edges[i][j+1][k+1]++;
- }
- }
- else
- {
- int i, x, j, y;
- in >> i >> x >> j >> y;
- i++, x++, j++, y++;
- if(i + 1 == j)
- out << edges[i][x][y] << "\n";
- else
- {
- int a = 0, b = 0;
- for(int ob = 1; ob <= K; ++ob)
- {
- a += edges[i][x][ob];
- b += edges[j-1][ob][y];
- }
- cout << a << " " << b << "\n";
- int rasp = (a * b * arb.Query(i+1, j-1)) % MOD;
- out << rasp << "\n";
- }
- }
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement