虽然是补题但分享一个奇怪的思路?

主要就是,最后一维搜索可以改成 __int128 并起来求最高位:

形式化设 f[S][T] 为数字集合为 S(1 到 1023),保留的灯管集合为 T(1 到 127)是否能区分集合中的每个数?

然后最后一维的搜索相当于枚举 S1,S2,Sn,找到元素个数最少的 T;使得 f[S1][T], f[S2][T], f[Sn][T] 都为 1?

那直接重排 T 使得 T 随着 popcount 递增,然后预处理出 f[S] 代表高位,然后用 __int128 并起来即可。

由于这个操作直接压掉了最后一层 2^7 搜索,所以跑得飞快。

详细见代码,可能略丑:

#include<bits/stdc++.h>
#define up(a,b,c)for(int a=b;a<=c;++a)
const int hjm[10][7]={
{1,1,1,0,1,1,1},//0
{0,0,1,0,0,1,0}, //1
{1,0,1,1,1,0,1},//2
{1,0,1,1,0,1,1},//3
{0,1,1,1,0,1,0},//4
{1,1,0,1,0,1,1},//5
{1,1,0,1,1,1,1},//6
{1,0,1,0,0,1,0},//7
{1,1,1,1,1,1,1},//8
{1,1,1,1,0,1,1},//9
};
using namespace std;
int hj[10],f[1<<10][1<<7],c[1<<10],chj[1<<10],id[1<<7],di[1<<7];
__uint128_t F[1<<10];
int T,n,m,x[110][4],bu2[1<<14];
bool cmp(int x,int y){
	return __builtin_popcount(x)<__builtin_popcount(y);
}
int hbt(__uint128_t x){
	for(int z=0;z<128;++z)
		if(x>>z&1)return z;
	return 0;
}
int main(){
//	cin.tie(0)->sync_with_stdio(0);
	up(i,0,9){
		up(j,0,6)hj[i]|=hjm[i][j]<<j;
	}
	up(S,0,(1<<10)-1)chj[S]=114514;
	up(S,0,(1<<10)-1)
		up(T,0,(1<<7)-1){
			up(i,0,9)
				if(S>>i&1)c[hj[i]&T]=0;
			bool ok=1;
			up(i,0,9)if(S>>i&1){
				if(c[hj[i]&T]){
					ok=0;break;
				}else c[hj[i]&T]=1;
			}
			f[S][T]=ok;
			if(ok){
				chj[S]=min(__builtin_popcount(T),chj[S]);
//				if(S==(1<<10)-1)cout<<T<<'\n'; 
			}
		}
	iota(id,id+(1<<7),0);
	sort(id,id+(1<<7),cmp);
	up(T,0,(1<<7)-1)di[T]=__builtin_popcount(id[T]);
//	up(T,0,(1<<7)-1)cout<<id[T]<<'\n';
//	cout<<chj[(1<<10)-1]<<'\n';
	up(S,0,(1<<10)-1)
		up(T,0,(1<<7)-1)
			F[S]|=__int128(f[S][id[T]])<<T;
//	__uint128_t x=F[(1<<10)-1];
	
//	cout<<di[hbt(F[(1<<10)-1])];
	int _;cin>>_;
	while(_--){
		cin>>n>>m;
		up(i,1,n){
			string s;cin>>s; 
			up(j,0,m-1)x[i][j]=s[j]-'0';
		}
		if(m==1){
			int S=0;
			up(i,1,n)S|=1<<x[i][0];
			cout<<di[hbt(F[S])]<<'\n';
		}else if(m==2){
			int ans=114514;
			up(S1,0,(1<<7)-1)
				up(S2,0,(1<<7)-1){
					up(i,1,n)
						bu2[(S1&hj[x[i][0]])<<7|(S2&hj[x[i][1]])]=0;
					bool ok=1;
					up(i,1,n)
						if(bu2[(S1&hj[x[i][0]])<<7|(S2&hj[x[i][1]])]){
							ok=0;break;
						}
						else{
							bu2[(S1&hj[x[i][0]])<<7|(S2&hj[x[i][1]])]=1;
						}
					if(ok)ans=min(ans,__builtin_popcount(S1<<7|S2));
				}
			cout<<ans<<'\n'; 
		}else if(m==3){
			int ans=114514;
			up(S1,0,(1<<7)-1)
				up(S2,0,(1<<7)-1){
					up(i,1,n)
						bu2[(S1&hj[x[i][0]])<<7|(S2&hj[x[i][1]])]=0;
					bool ok=1;
					up(i,1,n){
						int &G=bu2[(S1&hj[x[i][0]])<<7|(S2&hj[x[i][1]])];
						if(G>>x[i][2]&1){
							ok=0;break;
						}
						else{
							G|=1<<x[i][2];
						}
					}
					if(ok){
						__uint128_t T=-1;
						up(i,1,n){
							int S=bu2[(S1&hj[x[i][0]])<<7|(S2&hj[x[i][1]])];
							T&=F[S];
						}
						ans=min(ans,__builtin_popcount(S1<<7|S2)+di[hbt(T)]);
					}
				}
			cout<<ans<<'\n';
		}
	}
	return 0;
}