• Codeforces Gym101518F:Dimensional Warp Drive(二分+高斯消元)


    题目链接

    题意

    给出一个11元组A和11元组B,给出n个11元方程,每个方程有一个日期,要让A变成B,问最少需要日期多少才可以变。

    思路

    因为日期满足单调性,所以可以二分答案。判断的时候就是高斯消元套模板,这个模板是要能对11取模的(因为说了数字在0到10之间)。

    #include <bits/stdc++.h>
    using namespace std;
    const int MOD = 11;
    const int MAXN = 1011;
    struct Node {
        int num[11];
        int tid;
    
        bool operator < (const Node &rhs) const {
            return tid < rhs.tid;
        }
    } init[MAXN];
    int a[12][MAXN];//增广矩阵
    int x[MAXN];//最后得到的解集
    int s[11], e[11];
    
    inline int gcd(int a,int b) {
        while(b != 0) {
            int t = b;
            b = a%b;
            a = t;
        }
        return a;
    }
    
    inline int lcm(int a,int b) {
        return a/gcd(a,b)*b;
    }
    
    long long inv(long long a,long long 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] != 0) {
                    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 = k; i < equ; i++)
            if(a[i][col] != 0)
                return 0;//无解
        return 1;
    }
    
    int check(int m) {
        int equ = 11, var = m + 1; // 行数和列数
        for(int i = 0; i < 11; i++)
            for(int j = 0; j <= m; j++)
                a[i][j] = init[j].num[i];
        for(int i = 0; i < 11; i++)
            a[i][var] = (e[i] - s[i] + MOD) % MOD;
        return Gauss(equ, var);
    }
    
    int main() {
        int t; scanf("%d", &t);
        while(t--) {
            int n; scanf("%d", &n);
            for(int i = 0; i < 11; i++) scanf("%d", &s[i]);
            for(int i = 0; i < 11; i++) scanf("%d", &e[i]);
            for(int i = 0; i < n; i++) {
                for(int j = 0; j < 11; j++) scanf("%d", &init[i].num[j]);
                scanf("%d", &init[i].tid);
            }
            sort(init, init + n);
            int l = 0, r = n - 1, ans = -1;
            while(l <= r) {
                int m = (l + r) >> 1;
                if(check(m)) {
                    ans = init[m].tid;
                    r = m - 1;
                } else {
                    l = m + 1;
                }
            }
            if(~ans) printf("%d
    ", ans);
            else puts("unreachable");
        } return 0;
    }
    
    
  • 相关阅读:
    AC自动机
    HDU
    2020牛客寒假算法基础集训营3 B 牛牛的DRB迷宫II
    POJ 3784 Running Median【维护动态中位数】
    CodeForces
    HDU 2444 The Accomodation of Students【二分图最大匹配问题】
    POJ 1201 Intervals【差分约束】
    POJ 2976 Dropping tests【0/1分数规划模板】
    2019牛客暑期多校训练营(第七场)A.String【最小表示法】
    POJ 1287 Networking【kruskal模板题】
  • 原文地址:https://www.cnblogs.com/fightfordream/p/7635865.html
Copyright © 2020-2023  润新知