题目链接.
异或方程组高斯消元例题。
每个元素选与不选设为未知数。
同一行同一列搞个方程。
至于是完全平方数就分解质因数,对每个质因子建一个方程。
答案是2的自由元个数次幂。
自由元个数=元的个数-有用方程的条数。
其实我到现在才知道高斯消元非三角矩阵的打法,感觉以前学了假的消元。
可以用bitset优化,很简单,这里不讲。
算法竞赛入门经典这本书里有一道类似的题,打法也是从那里copy的。
Code:
#include
#include
#include
#define fo(i, x, y) for(int i = x; i <= y; i ++)
#define min(a, b) ((a) < (b) ? (a) : (b))
using namespace std;
const int N = 21, mo = 1e9 + 7;
const int M = 1e5;
int T;
int p[M], bz[M];
int n, a[N][N], num[N][N];
int u[N][N][20], v[N][N][20];
int b[N * 100][N * N], tot;
set<int> s;
int ans = 1;
void Build() {
fo(i, 2, M) {
if(!bz[i]) p[++ p[0]] = i;
fo(j, 1, p[0]) {
int k = i * p[j];
if(k > M) break;
bz[k] = 1;
if(i % p[j] == 0) break;
}
}
}
void Clear() {
fo(i, 1, tot) fo(j, 0, n * n) b[i][j] = 0;
tot = 0;
}
void Built() {
scanf("%d", &n);
fo(i, 1, n) fo(j, 1, n) num[i][j] = (i - 1) * n + j;
fo(i, 1, n) {
b[++ tot][0] = 1;
fo(j, 1, n) b[tot][num[i][j]] = 1;
}
fo(j, 1, n) {
b[++ tot][0] = 1;
fo(i, 1, n) b[tot][num[i][j]] = 1;
}
fo(i, 1, n) fo(j, 1, n) scanf("%d", &a[i][j]);
fo(i, 1, n) {
fo(j, 1, n) {
int x = a[i][j]; u[i][j][0] = 0;
for(int k = 1; k <= p[0] && p[k] * p[k] <= x; k ++)
if(x % p[k] == 0) {
u[i][j][++ u[i][j][0]] = p[k];
v[i][j][u[i][j][0]] = 0;
while(x % p[k] == 0)
v[i][j][u[i][j][0]] ++, x /= p[k];
}
if(x > 1) u[i][j][++ u[i][j][0]] = x, v[i][j][u[i][j][0]] = 1;
fo(k, 1, u[i][j][0]) s.insert(u[i][j][k]);
}
}
while(!s.empty()) {
int x = *s.begin(); s.erase(x);
b[++ tot][0] = 0;
fo(i, 1, n) {
fo(j, 1, n) {
fo(k, 1, u[i][j][0]) if(u[i][j][k] == x && v[i][j][k] % 2)
b[tot][num[i][j]] = 1;
}
}
}
}
void W() {
fo(i, 1, tot) {
fo(j, 0, n * n) printf("%d ", b[i][j]);
printf("\n");
}
printf("\n");
}
int Solve(int m, int n) {
int i = 1, j = 1;
while(i <= m && j <= n) {
int r = i;
fo(k, i, m) if(b[k][j]) r = k;
if(b[r][j]) {
fo(k, 0, n) swap(b[i][k], b[r][k]);
fo(u, i + 1, m) if(b[u][j])
fo(k, 0, n) b[u][k] ^= b[i][k];
i ++;
}
j ++;
}
return n - i + 1;
}
void pd() {
fo(i, 1, tot) {
int bz = 1;
fo(j, 1, n * n) if(b[i][j]) {
bz = 0; break;
}
if(bz && b[i][0]) {
ans = 0; return;
}
}
}
int main() {
Build();
for(scanf("%d", &T); T; T --) {
Clear();
Built();
int r = Solve(tot, n * n);
ans = 1; fo(i, 1, r) ans = (ans * 2) % mo;
pd(); printf("%d\n", ans);
}
}