题目链接
第一行和第二行直接暴力枚举,然后维护三个数(以下三个数都为去掉第一行和第二行选过的数),第三行和第四行都有的数的个数two,和第三行自己拥有的数tone,第四行自己拥有的数fone。
那么第三行有两种情况,如果选到了tone,第四行随便选,贡献是
如果选到了two,第四行选择就少了一个,即
时间复杂度

#include <bits/stdc++.h>
using namespace std;
#define BUFF ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define DEBUG(var) cout << #var << "=" << var << '\n'
#define REP(i, a, n) for (int i = a; i <= n; ++i)
#define PER(i, n, a) for (int i = n; i >= a; --i)
#define LL int64_t
template<typename T>void Read(T &x){x=0;char ch=getchar();LL f=1;while(!isdigit(ch)){if(ch=='-')f*=-1;ch=getchar();}while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}x*=f;}
template<typename T,typename... Args>void Read(T &x,Args&... args){Read(x);Read(args...);}
template<typename T>int64_t __lcm(T a, T b){return a/__gcd(a,b)*b;}
mt19937_64 rng(chrono::steady_clock::now().time_since_epoch().count());
inline int64_t Rand(LL a,LL b) {return a + rng() % (b-a+1);}
inline int64_t QuickPow(LL base,LL n,LL Mod=0){LL ret(1);while(n){if(n&1){ret*=base;if(Mod)ret%=Mod;}base*=base;if(Mod)base%=Mod;n>>=1;}return Mod?ret%Mod:ret;}
inline int64_t Inv(LL x,LL p){return QuickPow(x,p-2,p);}
inline void gettime(){time_t rawtime;struct tm *ptminfo;time(&rawtime);ptminfo = localtime(&rawtime);printf("Current time: %02d-%02d-%02d %02d:%02d:%02d\n",ptminfo->tm_year + 1900, ptminfo->tm_mon + 1, ptminfo->tm_mday,ptminfo->tm_hour, ptminfo->tm_min, ptminfo->tm_sec);}
const double pi = acos(-1.0);
const LL kInf(1e18);
const LL kMod(998244353);
const LL kMax(1e5 + 10);
LL group(1),ii(1);
char str[5][5010];
vector<int>used;
int tone,fone,two;
LL res = 0;
int n;
int mp[10][5050];
void dfs(int deep){
    if(deep == 1){
        for(int i = 1;i <= n;i++){
            if(str[deep][i] == '1'){
                used.push_back(i);
                dfs(deep+1);
                used.pop_back();
            }
        }
    }
    else if(deep == 2){
        for(int i = 1;i <= n;i++){
            if(i == used.back())continue;
            if(str[deep][i] == '1'){
                used.push_back(i);
                dfs(deep+1);
                used.pop_back();
            }
        }
    }
    else{
        int twof = 0;;
        int tonef = 0;
        int fonef = 0;
        for(auto it:used){
            if(mp[3][it] == 1 && mp[4][it] == 1){
                two--;
                twof ++;
            }
            else if(mp[3][it] == 1){
                tone--;
                tonef ++;
            }
            else if(mp[4][it] == 1){
                fone--;
                fonef ++;
            }
        }
        //cout<<two<<" "<<tone<<" "<<fone<<'\n';
        res += tone*(two+fone)+two*(two-1+fone);
        //cout<<tone*(two+fone)+two*(two-1+fone)<<'\n';
        two+=twof;
        tone += tonef;
        fone += fonef;
    }
}
inline void Solve()
{
    /*write your code down here*/
    tone = 0;
    fone = 0;
    cin>>n;
    for(int j = 1;j <= 4;j++){
        scanf("%s",str[j]+1);
    }
    for(int i = 3;i <= 4;i++){
        for(int j = 1;j <= n;j++){
            if(str[i][j] == '1'){
                mp[i][j]++;
            }
        }
    }
    //puts("haha");
    for(int i = 1;i <= n;i++){
        if(mp[3][i] == 1&&mp[4][i] == 1){
            two++;
        }
        else if(mp[3][i] == 1){
            tone++;
        }
        else if(mp[4][i] == 1){
            fone++;
        }
    }
    //cout<<two<<" "<<tone<<" "<<fone<<'\n';
    dfs(1);
    cout<<res<<'\n';
}

int main()
{
    //Read(group);
    //gettime();
    for(;ii <= group;ii++)
    {
        Solve();
    }
    return 0;
}