Official

D - Three Days Ago Editorial by en_translator


In what case is a string \(s\) happy?
Of course, one can rearrange a string to obtain a repetition of the same string twice only if every digit occurs even number of times in \(s\).
Conversely, if it is satisfied, one can always rearrange it to obtain a repetition of the same string twice. (This can be done by distributing each character into the former and latter halves and sorting them in ascending order.)

How many substrings satisfy the rephrased condition?
Let \(R_{i,x}\) be the number of occurrences, modulo \(2\), of \(x\) in the first \(i\) characters ( \(0 \le i \le |S|\) ).

When \(S=\) 20230322:

       R_{i,x} ( x=0,1,...,9 )
i = 0  0000000000
i = 1  0010000000
i = 2  1010000000
i = 3  1000000000
i = 4  1001000000
i = 5  0001000000
i = 6  0000000000
i = 7  0010000000
i = 8  0000000000

Then, we can prove that

  • if \(R_i = R_j\) (\(i < j\)), the substring of \(S\) from \((i+1)\)-th through \(j\)-th characters is happy;
  • if \(R_i \neq R_j\) (\(i < j\)), the substring of \(S\) from \((i+1)\)-th through \(j\)-th characters is not happy.

The proof is as follows:

  • (first one) … for each digit, the parity at the \(i\)-th and \(j\)-th characters are the same, so every digit occurs even number of times.
  • (second one) … there exists a diit such that the parity at the \(i\)-th and \(j\)-th characters are different, so the digit occurs odd number of times.

Therefore, one can choose two distinct \(i\)s with the same \(R_i\) to obtain a happy substring corresponding to the pair.
One can find the sum of the numbers of such choices for \(2^{10}\) possible \(R_i\)s (sample code 1), or accumulate the number of previous occurrences of the element when inspecting the later elements (sample code 2).

Sample code 1 (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  string s;
  cin >> s;
  map<vector<int>,long long> mp;
  vector<int> cnt(10,0);
  mp[cnt]++;
  for(auto &nx : s){
    cnt[nx-'0']++;
    cnt[nx-'0']%=2;
    mp[cnt]++;
  }
  long long res=0;
  for(auto &nx : mp){
    long long x=nx.second;
    res+=(x*(x-1))/2;
  }
  cout << res << "\n";
  return 0;
}

Sample code 2 (C++):

#include<bits/stdc++.h>

using namespace std;

int main(){
  string s;
  cin >> s;
  int flag=0;
  vector<long long> bk(1024,0);
  bk[0]++;
  long long res=0;
  for(auto &nx : s){
    flag^=(1<<(nx-'0'));
    res+=bk[flag];
    bk[flag]++;
  }
  cout << res << "\n";
  return 0;
}

posted:
last update: