#include <iostream>
#include <vector>
#include <string>
#include <algorithm>
using namespace std;
typedef long long ll;
// Używamy dwóch baz dla bezpieczeństwa
const ll MOD1 = 1e9 + 7;
const ll MOD2 = 1e9 + 9;
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
string a, b, c;
cin >> a >> b >> c;
int n = a.size();
// v1[i] będzie przechowywać (Wartość(A[i..n]) + Wartość(B[i..n]) - Wartość(C[i..n])) % MOD
vector<pair<ll, ll>> v(n + 1);
ll h1 = 0, h2 = 0;
ll p1 = 1, p2 = 1;
// Idziemy od prawej do lewej, obliczając wartości sufiksowe
v[n] = {0, 0};
for (int i = n - 1; i >= 0; i--) {
ll digit_a = a[i] - '0';
ll digit_b = b[i] - '0';
ll digit_c = c[i] - '0';
// Aktualizujemy hasz sumy sufiksowej: (A_suf + B_suf - C_suf)
h1 = (h1 + (digit_a + digit_b - digit_c) * p1) % MOD1;
if (h1 < 0) h1 += MOD1;
h2 = (h2 + (digit_a + digit_b - digit_c) * p2) % MOD2;
if (h2 < 0) h2 += MOD2;
v[i] = {h1, h2};
p1 = (p1 * 10) % MOD1;
p2 = (p2 * 10) % MOD2;
}
// Sortujemy wszystkie hasze sufiksowe.
// Jeśli v[i] == v[j+1], oznacza to, że fragment [i, j] sumuje się do 0.
sort(v.begin(), v.end());
ll wynik = 0;
ll count = 1;
for (int i = 1; i <= n; i++) {
if (v[i] == v[i - 1]) {
count++;
} else {
// Z k takich samych haszy możemy stworzyć k*(k-1)/2 par (i, j)
wynik += (count * (count - 1)) / 2;
count = 1;
}
}
wynik += (count * (count - 1)) / 2;
cout << wynik << endl;
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 | #include <iostream> #include <vector> #include <string> #include <algorithm> using namespace std; typedef long long ll; // Używamy dwóch baz dla bezpieczeństwa const ll MOD1 = 1e9 + 7; const ll MOD2 = 1e9 + 9; int main() { ios_base::sync_with_stdio(false); cin.tie(NULL); string a, b, c; cin >> a >> b >> c; int n = a.size(); // v1[i] będzie przechowywać (Wartość(A[i..n]) + Wartość(B[i..n]) - Wartość(C[i..n])) % MOD vector<pair<ll, ll>> v(n + 1); ll h1 = 0, h2 = 0; ll p1 = 1, p2 = 1; // Idziemy od prawej do lewej, obliczając wartości sufiksowe v[n] = {0, 0}; for (int i = n - 1; i >= 0; i--) { ll digit_a = a[i] - '0'; ll digit_b = b[i] - '0'; ll digit_c = c[i] - '0'; // Aktualizujemy hasz sumy sufiksowej: (A_suf + B_suf - C_suf) h1 = (h1 + (digit_a + digit_b - digit_c) * p1) % MOD1; if (h1 < 0) h1 += MOD1; h2 = (h2 + (digit_a + digit_b - digit_c) * p2) % MOD2; if (h2 < 0) h2 += MOD2; v[i] = {h1, h2}; p1 = (p1 * 10) % MOD1; p2 = (p2 * 10) % MOD2; } // Sortujemy wszystkie hasze sufiksowe. // Jeśli v[i] == v[j+1], oznacza to, że fragment [i, j] sumuje się do 0. sort(v.begin(), v.end()); ll wynik = 0; ll count = 1; for (int i = 1; i <= n; i++) { if (v[i] == v[i - 1]) { count++; } else { // Z k takich samych haszy możemy stworzyć k*(k-1)/2 par (i, j) wynik += (count * (count - 1)) / 2; count = 1; } } wynik += (count * (count - 1)) / 2; cout << wynik << endl; return 0; } |
English