Skip to content

Commit c63e1bb

Browse files
committed
Dodano rozwiązanie zadania 'Kurs szybkiego czytania' z XXII OI
1 parent 50bb786 commit c63e1bb

File tree

1 file changed

+126
-0
lines changed
  • rozwiazania/xxii/etap2/dzien2/kur

1 file changed

+126
-0
lines changed
Lines changed: 126 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,126 @@
1+
// Rozwiązanie zadania 'Kurs szybkiego czytania' z II etapu XXII OI.
2+
// Autor rozwiązania: Paweł Putra
3+
// Złożoność czasowa: O(m * log(m))
4+
// Złożoność pamięciowa: O(m)
5+
// Punkty: 100 (upsolve)
6+
7+
#include <iostream>
8+
#include <string>
9+
#include <algorithm>
10+
#include <numeric>
11+
#include <vector>
12+
#define sz(x) (int)(x).size()
13+
#define dbg(x) #x << " = " << x << " "
14+
using namespace std;
15+
using ll = long long;
16+
vector<pair<int, int>> pref;
17+
ll n, a, b, p, m;
18+
void dodaj(int l, int r) {
19+
if (l <= r) {
20+
pref.emplace_back(l, 1);
21+
pref.emplace_back(r+1, -1);
22+
} else {
23+
pref.emplace_back(0, 1);
24+
pref.emplace_back(r+1, -1);
25+
pref.emplace_back(l, 1);
26+
}
27+
}
28+
29+
inline int MOD(ll x) {
30+
ll res = (x % n);
31+
if (res < 0) res += n;
32+
return res;
33+
}
34+
35+
int gcd(int a, int b, int &x, int &y) {
36+
if (b == 0) {
37+
x = 1;
38+
y = 0;
39+
return a;
40+
}
41+
42+
int x1, y1;
43+
int d = gcd(b, a % b, x1, y1);
44+
x = y1;
45+
y = x1 - (a / b) * y1;
46+
return d;
47+
}
48+
49+
ll inv(ll a) {
50+
int x, y;
51+
gcd(a, n, x, y);
52+
return x;
53+
}
54+
55+
ll loc(ll x) {
56+
static ll a_inv = inv(a);
57+
return MOD((-b + x) * a_inv);
58+
}
59+
60+
int32_t main() {
61+
ios_base::sync_with_stdio(0); cin.tie(0);
62+
cin >> n >> a >> b >> p >> m;
63+
64+
string s;
65+
cin >> s;
66+
67+
// Wyliczam p_0 = -b / a mod n.
68+
ll p_0 = loc(0);
69+
70+
// Wyliczam p_1 = (-b + 1) / a mod n.
71+
ll p_1 = loc(1);
72+
73+
ll roz = llabs(p_1 - p_0);
74+
75+
pref.emplace_back(0, 0);
76+
pref.emplace_back(n-1, 0);
77+
for (int k = 0; k < m; k++) {
78+
if (s[k] == '0') {
79+
int l = MOD(0 - k * a);
80+
int r = MOD(p - 1 - k * a);
81+
82+
dodaj(l, r);
83+
} else {
84+
int l = MOD(p - k * a);
85+
int r = MOD(n - 1 - k * a);
86+
dodaj(l, r);
87+
}
88+
}
89+
90+
// Nie chcę liczyć wystąpień cyklicznych,
91+
// czyli takich że pierwsza litera jest na pozycji > n-m.
92+
// No to po prostu sobie tam odejmę jedynkę w punkcie żeby skipnąć :)
93+
for (int i = n-m+1; i < n; i++) {
94+
int x = MOD(a*i+b);
95+
pref.emplace_back(x, -1);
96+
pref.emplace_back(x+1, 1);
97+
}
98+
99+
vector<int> ord(pref.size());
100+
iota(ord.begin(), ord.end(), 0);
101+
sort(ord.begin(), ord.end(), [](auto lhs, auto rhs) {
102+
return pref[lhs].first < pref[rhs].first;
103+
});
104+
105+
int i = 0;
106+
int sum = 0, last = -1;
107+
int wynik = 0;
108+
while (i < sz(pref)) {
109+
auto [k, v] = pref[ord[i]];
110+
while (i + 1 < sz(pref) && k == pref[ord[i+1]].first) {
111+
i++;
112+
v += pref[ord[i]].second;
113+
}
114+
115+
if (sum == m) {
116+
wynik += k - last;
117+
}
118+
119+
sum += v;
120+
last = k;
121+
i++;
122+
}
123+
124+
cout << wynik << "\n";
125+
}
126+

0 commit comments

Comments
 (0)