# 【题解】Function HDU 6823 2020杭电多校5 线性基 抽象代数

### 题意

subtask1是，让你构造出这样的一个映射$$f$$，如果不存在输出无解，否则，他会告诉你一些$$x$$，你要告诉他对应的$$f(x)$$，通过这样的方法检验正确性

subtaks2是，给你一个映射$$f$$，还有一些$$x$$和对应的$$f(x)$$，问你这组解是否合法

### 题解

$f(x) = y \land f(y) = 0 \longrightarrow f(x \oplus y) = f(x) \oplus f(y) = f(x) = y \in K$

$$G$$的rank是$$r$$，从$$r$$个线性无关向量中任取$$r/2$$个，都可以张成这样一个Kernal，并且可以构造出符合条件的$$f$$，构造如下

### 代码

#include <bits/stdc++.h>

using namespace std;
typedef long long ll;
const int N = 1000010;
int _w;

int n;
ll a[N];

struct Basis {
ll b[60];

void clear() {
memset(b, 0, sizeof b);
}
bool insert( ll x ) {
for( int i = 0; i < 60; ++i )
if( x & (1LL << i) ) {
if( b[i] ) {
x ^= b[i];
} else {
b[i] = x;
for( int j = i+1; j < 60; ++j )
if( b[j] )
if( b[i] & (1LL << j) )
b[i] ^= b[j];
for( int j = 0; j < i; ++j )
if( b[j] & (1LL << i) )
b[j] ^= b[i];
return true;
}
}
return false;
}
int size() {
int ans = 0;
for( int i = 0; i < 60; ++i )
ans += bool(b[i]);
return ans;
}
bool inside( ll x ) {
for( int i = 0; i < 60; ++i )
if( x & (1LL << i) ) {
if( b[i] ) {
x ^= b[i];
} else {
return false;
}
}
return true;
}
};

void construct() {
Basis bas;
bas.clear();
for( int i = 1; i <= n; ++i )
bas.insert( a[i] );
if( bas.size() % 2 == 1 ) {
puts("NoSolution");
int m;
_w = scanf( "%d", &m );
while( m-- ) {
ll x;
_w = scanf( "%lld", &x );
}
} else {
puts("HaveSolution");
vector<int> bit;
for( int i = 0; i < 60; ++i )
if( bas.b[i] )
bit.push_back(i);
int sz = (int)bit.size();
int q;
_w = scanf( "%d", &q );
while( q-- ) {
ll x;
_w = scanf( "%lld", &x );
if( bas.inside(x) ) {
ll y = 0;
for( int i = sz/2; i < sz; ++i ) {
int b = bit[i];
if( x & (1LL << b) )
y ^= bas.b[bit[i-sz/2]];
}
printf( "%lld\n", y );
} else {
puts("-1");
}
}
}
}

namespace Check {
typedef pair<ll,ll> pii;

int m;
pii xy[N];

vector<ll> zero;
pii by[60];

void insert_by( pii now ) {
ll x = now.first;
ll y = now.second;
for( int i = 0; i < 60; ++i )
if( y & (1LL << i) ) {
if( by[i].second == 0 ) {
by[i] = pii(x, y);
for( int j = i+1; j < 60; ++j )
if( by[j].second )
if( by[i].second & (1LL << j) ) {
by[i].second ^= by[j].second;
by[i].first ^= by[j].first;
}
for( int j = 0; j < i; ++j )
if( by[j].second & (1LL << i) ) {
by[j].second ^= by[i].second;
by[j].first ^= by[i].first;
}
return;
} else {
y ^= by[i].second;
x ^= by[i].first;
}
}
zero.push_back(x);
}

void check() {
Basis bas;
bas.clear();
for( int i = 1; i <= n; ++i )
bas.insert( a[i] );
string state;
cin >> state;
if( (state == "NoSolution" && bas.size() % 2 == 0) ||
(state == "HaveSolution" && bas.size() % 2 == 1) ) {
puts("No");
if( state == "HaveSolution" ) {
int m;
_w = scanf( "%d", &m );
while( m-- ) {
ll x, fx;
_w = scanf( "%lld%lld", &x, &fx );
}
}
} else {
if( state == "NoSolution" ) {
puts("Yes");
return;
}
_w = scanf( "%d", &m );
for( int i = 1; i <= m; ++i ) {
ll x, y;
_w = scanf( "%lld%lld", &x, &y );
xy[i] = pii(x, y);
}
for( int i = 1; i <= m; ++i ) {
if( (bas.inside( xy[i].first ) && xy[i].second == -1) ||
(bas.inside( xy[i].first ) == false && xy[i].second != -1) ) {
puts("No");
return;
}
}
zero.clear();
memset(by, 0, sizeof by);
for( int i = 1; i <= m; ++i )
if( xy[i].second != -1 )
insert_by( xy[i] );
Basis bas_ker;
bas_ker.clear();
for( ll ker : zero )
bas_ker.insert(ker);
for( int i = 0; i < 60; ++i )
if( by[i].second )
bas_ker.insert( by[i].second );
if( bas_ker.size() > bas.size() / 2 ) {
puts("No");
return;
}
Basis bas_x;
bas_x.clear();
for( int i = 0; i < 60; ++i )
if( by[i].second ) {
if( bas_x.insert( by[i].first ) == false ) {
puts("No");
return;
}
if( bas_ker.inside( by[i].first ) ) {
puts("No");
return;
}
}
puts("Yes");
}
}

}
using Check::check;

int main() {
int T;
_w = scanf( "%d", &T );
while( T-- ) {
_w = scanf( "%d", &n );
for( int i = 1; i <= n; ++i )
_w = scanf( "%lld", a+i );
string op;
cin >> op;
if( op == "construct" ) {
construct();
} else {
check();
}
}
return 0;
}

posted @ 2020-10-22 00:23  mlystdcall  阅读(316)  评论(0编辑  收藏  举报