这是2017浙大校赛的最后一道题(还有一道实在不会做),感觉并没有什么特别难的题目,写的题解好像在以后来看也没什么参考价值。。
题意
每一列作为一个元素,是否存在一个排列使得结果刚好是标准模式
思路
由于排列总共就 7! 种,直接打表就好了,但是因为组数较多,每次都 O(n) 查找会超时,所以可以将状态表示成一个整数(刚好63位,longlong能够存的下),每次二分找答案,由于存在空着的元组,所以排列变成 29∗7! 种,但是每次搜索很快( log(29∗7!) ),时间满足要求
代码
#include <bits/stdc++.h>
#define mem(a,b) memset(a,b,sizeof(a))
#define rep(i,a,b) for(int i=a;i<b;i++)
#define sc(a) scanf("%d",&a)
const int INF=0x3f3f3f3f;
const int maxn=2e5+50;
const int mod=1e9+7;
const double eps=1e-8;
#define pii pair<int,int>
typedef long long ll;
typedef unsigned int ui;
using namespace std;
int pattern[10][7]{
0,0,0,0,0,0,0,
1,0,0,1,1,1,1,
0,0,1,0,0,1,0,
0,0,0,0,1,1,0,
1,0,0,1,1,0,0,
0,1,0,0,1,0,0,
0,1,0,0,0,0,0,
0,0,0,1,1,1,1,
0,0,0,0,0,0,0,
0,0,0,0,1,0,0
};
char buf[10];
int s7[7];
int getXFromS7(int s7[]){
int ret=0;
for(int i=0;i<7;i++){
if(s7[i]) ret+=1<<(6-i);
}
return ret;
}
struct Pattern{
ll s[10];
int getFrom(int perm[],int x){
for(int i=0;i<7;i++){
s7[i]=pattern[x][perm[i]];
}
return getXFromS7(s7);
}
void init(int perm[]){
mem(s,0);
rep(i,1,10) s[i]=getFrom(perm,i);
}
void print(){
rep(i,1,10){
printf("%lld ",s[i]);
}
puts("");
}
void read(){
mem(s,0);
int n; sc(n);
rep(i,0,n){
int x; sc(x);
scanf(" %s",buf);
rep(j,0,7){
s7[j]=buf[j]-'0';
}
s[x]=getXFromS7(s7);
}
}
ll toLL(){
ll ret=0;
rep(i,1,10){
ret+=s[i]<<((i-1)*7);
}
return ret;
}
};
set<ll> ans;
void getP(Pattern &p,int dep){
if(dep==10) {
//p.print();
ans.insert(p.toLL());
return;
}
ll tmp=p.s[dep];
p.s[dep]=0;
getP(p,dep+1);
p.s[dep]=tmp;
getP(p,dep+1);
}
void init(){
int perm[7];
rep(i,0,7) perm[i]=i;
do{
Pattern p;
p.init(perm);
//p.print();
getP(p,1);
}while(next_permutation(perm,perm+7));
//for(auto i:ans) cout<<"= ="<<i<<endl;
}
Pattern tar;
int main()
{
#ifndef ONLINE_JUDGE
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
#endif
init();
//printf("%d\n",ans.size());
int T; scanf("%d",&T);
while(T--){
tar.read();
puts(ans.find(tar.toLL())!=ans.end()?"YES":"NO");
}
return 0;
}