hdu 5755 Gambler Bo 高斯消元

时间:2023-03-08 20:18:01

题目链接

给n*m的方格, 每个格子有值{0, 1, 2}。 然后可以对格子进行操作, 如果选择了一个格子, 那么这个格子的值+2, 这个格子上下左右的格子+1, 并且模3。

问你将所有格子变成0的操作方法。

其实就是一个模3的方程组, 高斯消元就可以了。 不知道为什么昨天比赛就是想不到......

#include <iostream>
#include <vector>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <complex>
#include <cmath>
#include <map>
#include <set>
#include <string>
#include <queue>
#include <stack>
#include <bitset>
using namespace std;
#define pb(x) push_back(x)
#define ll long long
#define mk(x, y) make_pair(x, y)
#define lson l, m, rt<<1
#define mem(a) memset(a, 0, sizeof(a))
#define rson m+1, r, rt<<1|1
#define mem1(a) memset(a, -1, sizeof(a))
#define mem2(a) memset(a, 0x3f, sizeof(a))
#define rep(i, n, a) for(int i = a; i<n; i++)
#define fi first
#define se second
typedef complex <double> cmx;
typedef pair<int, int> pll;
const double PI = acos(-1.0);
const double eps = 1e-;
const int mod = ;
const int inf = ;
const int dir[][] = { {-, }, {, }, {, -}, {, } };
int a[][];
int n, b[], x[], m;
int gcd(int a, int b)
{
return b?gcd(b, a%b):a;
}
int lcm(int a, int b)
{
return a/gcd(a, b)*b;
}
ll inv(ll a, ll m)
{
if(a == )
return ;
return inv(m%a, m)*(m-m/a)%m;
}
int gauss(int equ, int var)
{
int max_r, col, k;
for(k = , col = ; k < equ && col < var; k++, col++) {
max_r = k;
for(int i = k + ; i < equ; i ++) {
if(abs(a[i][col]) > abs(a[max_r][col]))
max_r = i;
}
if(a[max_r][col] == ) {
k--;
continue;
}
if(max_r != k) {
for(int j = col; j < var+; j++) {
swap(a[k][j], a[max_r][j]);
}
}
for(int i = k + ; i < equ; i++) {
if(a[i][col]) {
int LCM = lcm(abs(a[i][col]), abs(a[k][col]));
int ta = LCM/abs(a[i][col]);
int tb = LCM/abs(a[k][col]);
if(a[i][col] * a[k][col] < )
tb = -tb;
for(int j = col; j < var+; j++) {
a[i][j] = ((a[i][j]*ta - a[k][j]*tb)%mod+mod)%mod;
}
}
}
for(int i = var-; i >= ; i--) {
int tmp = a[i][var];
for(int j = i+; j < var; j++) {
if(a[i][j]) {
tmp -= a[i][j]*x[j];
tmp = (tmp%mod+mod)%mod;
}
}
x[i] = a[i][i]*tmp%mod;
}
}
}
int check(int x)
{
return x >= && x < n*m;
}
int main()
{
int t;
cin>>t;
while(t--) {
scanf("%d%d", &n, &m);
for(int i = ; i < n*m; i++) {
scanf("%d", &b[i]);
}
mem(x);
mem(a);
for(int i = ; i < n*m; i++) {
int u = i-m, d = i+m;
int l = i-, r = i+;
if(check(u)) {
a[i][u] = ;
}
if(check(d)) {
a[i][d] = ;
}
if(check(l)&&i%m!=) {
a[i][l] = ;
}
if(check(r)&&(i+)%m!=) {
a[i][r] = ;
}
a[i][i] = ;
a[i][n*m] = (-b[i])%;
}
n *= m;
gauss(n, n);
int cnt = ;
for(int i = ; i < n; i++) {
if(x[i])
cnt += x[i];
}
printf("%d\n", cnt);
for(int i = ; i < n; i++) {
while(x[i]) {
printf("%d %d\n", i/m+, i%m+);
x[i]--;
}
}
}
return ;
}