虽然是补题但分享一个奇怪的思路?
主要就是,最后一维搜索可以改成 __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;
}

京公网安备 11010502036488号