题目描述见链接 .
直接上 高斯消元, 发现只能得到 ,
代码,
#include<bits/stdc++.h>
#define reg register
const double eps = 1e-12;
int read(){
char c;
int s = 0, flag = 1;
while((c=getchar()) && !isdigit(c))
if(c == '-'){ flag = -1, c = getchar(); break ; }
while(isdigit(c)) s = s*10 + c-'0', c = getchar();
return s * flag;
}
const int maxn = 105;
int N;
int M;
double A[maxn][maxn];
char Tmp[25];
int Fuck(){
int t = 1;
for(reg int i = 1; i <= M && t <= N; i ++, t ++){
int max_id = t;
for(reg int j = t+1; j <= M; j ++) if(A[j][i] > A[max_id][i]) max_id = j;
if(!A[max_id][i]){ t --; continue ; }
std::swap(A[max_id], A[t]);
for(reg int j = N+1; j >= i; j --) A[t][j] /= A[t][i];
if(A[t][i] < 0) for(reg int j = 1; j <= N+1; j ++) A[t][j] = -A[t][j];
for(reg int j = t+1; j <= M; j ++){
if(!A[j][i]) continue ;
for(reg int k = N+1; k >= i; k --) A[j][k] -= A[j][i] * A[t][k];
}
}
t --;
for(reg int i = t; i >= 1; i --)
for(reg int j = i+1; j <= N; j ++) A[i][N+1] -= A[j][N+1]*A[i][j], A[i][j] = 0;
for(reg int i = t+1; i <= N; i ++) if(fabs(A[i][N+1]) > eps) return -1;
if(t < N) return 0;
return 1;
}
int main(){
N = read(), M = read();
for(reg int i = 1; i <= M; i ++){
scanf("%s", Tmp+1);
for(reg int j = 1; j <= N; j ++) A[i][j] = Tmp[j] - '0';
A[i][N+1] = read();
}
int flag = Fuck();
if(flag == -1) printf("IMPOSSIBLE
");
else if(flag == 0) printf("NOT UNIQUE
");
else for(reg int i = 1; i <= N; i ++) printf("%.0lf", fabs(A[i][N+1]));
return 0;
}
原来是因为当方程的个数小于 个, 且仅有一种合法方案使得方程组成立时, 高斯消元 是判其多解的 .
例如这组数据:
5 1
11111 5
直接将每个方程化为二进制形式, 暴力搜索, 搜索 时剪剪枝就可以 了 …
#include<bits/stdc++.h>
#define reg register
const int maxn = 105;
int N;
int M;
int flag;
int flag_2;
int ans[maxn];
int res[maxn];
char Smp[22];
struct Node{ int max_bit, zt, val; } A[maxn];
bool cmp(Node a, Node b){ return a.max_bit < b.max_bit; }
bool check(const int &lev){
for(reg int i = 1; i <= M; i ++){
if(A[i].max_bit > lev) break ;
int s = 0;
for(reg int j = 1; j <= N; j ++) if(A[i].zt & (1<<j-1)) s += ans[j];
if(s != A[i].val) return 0;
}
return 1;
}
void DFS(int k, int zt){
if(flag_2) return ;
if(k == N+1){
if(check(k+1)){
if(flag){ flag_2 = 1; return ; }
flag = 1;
for(reg int i = 1; i <= N; i ++) res[i] = ans[i];
}
return ;
}
ans[k] = 1;
if(check(k)) DFS(k+1, zt|(1<<k-1));
ans[k] = 0; DFS(k+1, zt);
}
int main(){
scanf("%d%d", &N, &M);
for(reg int i = 1; i <= M; i ++){
scanf("%s", Smp+1);
for(reg int j = 1; j <= N; j ++){
A[i].zt |= ((Smp[j]-'0') << (j-1));
if(Smp[j] == '1') A[i].max_bit = j;
}
scanf("%d", &A[i].val);
}
std::sort(A+1, A+M+1, cmp);
DFS(1, 0);
if(!flag) printf("IMPOSSIBLE
");
else if(flag_2) printf("NOT UNIQUE
");
else for(reg int i = 1; i <= N; i ++) printf("%d", res[i]);
return 0;
}