zoukankan      html  css  js  c++  java
  • hdu 5755 Gambler Bo 高斯消元

    题目链接

    给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-8;
    const int mod = 3;
    const int inf = 1061109567;
    const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} };
    int a[901][902];
    int n, b[902], x[902], 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 == 1)
            return 1;
        return inv(m%a, m)*(m-m/a)%m;
    }
    int gauss(int equ, int var)
    {
        int max_r, col, k;
        for(k = 0, col = 0; k < equ && col < var; k++, col++) {
            max_r = k;
            for(int i = k + 1; i < equ; i ++) {
                if(abs(a[i][col]) > abs(a[max_r][col]))
                    max_r = i;
            }
            if(a[max_r][col] == 0) {
                k--;
                continue;
            }
            if(max_r != k) {
                for(int j = col; j < var+1; j++) {
                    swap(a[k][j], a[max_r][j]);
                }
            }
            for(int i = k + 1; 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] < 0)
                        tb = -tb;
                    for(int j = col; j < var+1; j++) {
                        a[i][j] = ((a[i][j]*ta - a[k][j]*tb)%mod+mod)%mod;
                    }
                }
            }
            for(int i = var-1; i >= 0; i--) {
                int tmp = a[i][var];
                for(int j = i+1; 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 >=0 && x < n*m;
    }
    int main()
    {
        int t;
        cin>>t;
        while(t--) {
            scanf("%d%d", &n, &m);
            for(int i = 0; i < n*m; i++) {
                scanf("%d", &b[i]);
            }
            mem(x);
            mem(a);
            for(int i = 0; i < n*m; i++) {
                int u = i-m, d = i+m;
                int l = i-1, r = i+1;
                if(check(u)) {
                    a[i][u] = 1;
                }
                if(check(d)) {
                    a[i][d] = 1;
                }
                if(check(l)&&i%m!=0) {
                    a[i][l] = 1;
                }
                if(check(r)&&(i+1)%m!=0) {
                    a[i][r] = 1;
                }
                a[i][i] = 2;
                a[i][n*m] = (3-b[i])%3;
            }
            n *= m;
            gauss(n, n);
            int cnt = 0;
            for(int i = 0; i < n; i++) {
                if(x[i])
                    cnt += x[i];
            }
            printf("%d
    ", cnt);
            for(int i = 0; i < n; i++) {
                while(x[i]) {
                    printf("%d %d
    ", i/m+1, i%m+1);
                    x[i]--;
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    Codeforces 1255B Fridge Lockers
    Codeforces 1255A Changing Volume
    Codeforces 1255A Changing Volume
    leetcode 112. 路径总和
    leetcode 129. 求根到叶子节点数字之和
    leetcode 404. 左叶子之和
    leetcode 104. 二叉树的最大深度
    leetcode 235. 二叉搜索树的最近公共祖先
    450. Delete Node in a BST
    树的c++实现--建立一棵树
  • 原文地址:https://www.cnblogs.com/yohaha/p/5710264.html
Copyright © 2011-2022 走看看