公式

F - Oddly Similar 解説 by en_translator


A naive solution for this problem would be enumerating all pairs \((i,j)\), counting for each pair the number of \(k (1 \leq k \leq M)\) such that \(A_{i,k}=A_{j,k}\), and incrementing the answer if it is odd. However, it costs \(O(N^2M)\) time, which may not fit in the execution time limit depending on implementation.

For this problem, one can adopt the trick called bitset optimization to have a constant factor of \(\frac{1}{64}\). This way, we have \(\frac{2000^{3}}{64} = 125000000 \simeq 10^{8}\), which is fast enough.

Specifically, let \(B_{i,j}\) be the parity of the number of indices \(k\) such that \(A_{i,k}=A_{j,k}\); then each of \(B_1,B_2,\ldots,B_N\) can be encoded in a bitset. On implementation, for each \(k\) from \(1\) through \(M\), process \(A_{i,k}\) with the same value at once, and use XOR (exclusive OR) or bitsets appropriately.

For more details, refer to the sample code.

Sample code (C++):

#include<bits/stdc++.h>
using namespace std;

static constexpr size_t maxN=2000;
int main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int n,m;cin>>n>>m;
    vector<vector<int>>a(n,vector<int>(m));
    for(int i=0;i<n;++i){
        for(int j=0;j<m;++j){
            cin>>a[i][j];
        }
    }
    
    vector<bitset<maxN>>bt(n);
    vector<bitset<maxN>>bs(1000);
    for(int i=0;i<m;++i){
        for(int j=0;j<n;++j){
            bs[a[j][i]].set(j);
        }
        for(int j=0;j<n;++j){
            bt[j]^=bs[a[j][i]];
        }
        for(int j=0;j<n;++j){
            bs[a[j][i]].reset(j);
        }
    }

    int ans=0;
    for(int i=0;i<n;++i)ans+=bt[i].count();
    if(m&1)ans-=n;
    cout<<ans/2<<endl;
}

投稿日時:
最終更新: