• 线代(高斯消元法、线性基)


    一、高斯消元法

    1、将问题转化为矩阵方程,再转化为多个n元一次方程,从而使用高斯消元法

    使用高斯消元法的关键在于构造增广矩阵

    2、需求解的未知数可能是很多类型,例如浮点型、01型

    (1)、异或类型解

    1. bitset<maxn>a[maxn]; //a数组代表增广矩阵的系数,常数项在最后
    2. int ans[maxn], Free[maxn], cnt; //ans代表最后方程组的解,Free和cnt是自由元
    3. int Gauss(int equ, int var) //equ个方程组,var个位置数
    4. {
    5. int row, col, MaxRow;
    6. col = 0;
    7. for (row = 0; row < equ && col < var; row++, col++)
    8. {
    9. MaxRow = row;
    10. for (int i = row + 1; i < equ; i++)
    11. {
    12. if (abs(a[i][col]) > abs(a[MaxRow][col]))
    13. MaxRow = i;
    14. }
    15. if (MaxRow != row)
    16. {
    17. swap(a[row], a[MaxRow]);
    18. }
    19. if (a[row][col] == 0)
    20. {
    21. row--;
    22. Free[++cnt] = col;
    23. continue;
    24. }
    25. for (int i = row + 1; i < equ; i++)
    26. {
    27. if (a[i][col])
    28. a[i] ^= a[row];
    29. }
    30. }
    31. for (int i = row; i < equ; i++)
    32. {
    33. if (a[i][col])
    34. return -1;
    35. }
    36. if (row < var)
    37. return var - row;
    38. for (int i = var - 1; i >= 0; i--)
    39. {
    40. ans[i] = a[i][var];
    41. for (int j = i + 1; j < var; j++)
    42. {
    43. if (a[i][j])
    44. ans[i] ^= (a[i][j] && ans[j]);
    45. }
    46. }
    47. return 0;
    48. }

    (2)、浮点类型解

    1. double a[maxn][maxn], ans[maxn];
    2. int cnt, Free[maxn];
    3. int Gauss(int equ, int var)
    4. {
    5. for (int i = 0; i <= var; i++)
    6. {
    7. ans[i] = 0;
    8. Free[i] = 1;
    9. }
    10. int row, col, MaxRow;
    11. col = 0;
    12. for (row = 0; row < equ && col < var; row++, col++)
    13. {
    14. MaxRow = row;
    15. for (int i = row + 1; i < equ; i++)
    16. {
    17. if (fabs(a[i][col]) > fabs(a[MaxRow][col]))
    18. MaxRow = i;
    19. }
    20. if (MaxRow != row)
    21. {
    22. for (int i = row; i <= var; i++)
    23. swap(a[row][i], a[MaxRow][i]);
    24. }
    25. if (fabs(a[row][col]) < eps)
    26. {
    27. row--;
    28. continue;
    29. }
    30. for (int i = row + 1; i < equ; i++)
    31. {
    32. if (fabs(a[i][col]) > eps)
    33. {
    34. double temp = a[i][col] / a[row][col];
    35. for (int j = col; j <= var; j++)
    36. a[i][j] -= a[row][j] * temp;
    37. a[i][col] = 0;
    38. }
    39. }
    40. }
    41. for (int i = row; i < equ; i++)
    42. {
    43. if (fabs(a[i][col]) > eps)
    44. return -1;
    45. }
    46. double temp;
    47. if (row < var)
    48. {
    49. for (int i = row - 1; i >= 0; i--)
    50. {
    51. int free_num = 0, idx;
    52. for (int j = 0; j < var; j++)
    53. {
    54. if (a[i][j] && Free[j])
    55. {
    56. free_num++;
    57. idx = j;
    58. }
    59. }
    60. if (free_num > 1)
    61. continue;
    62. temp = a[i][var];
    63. for (int j = 0; j < var; j++)
    64. {
    65. if (a[i][j] && j != idx)
    66. temp -= a[i][j] * ans[j];
    67. }
    68. ans[idx] = temp / a[i][idx];
    69. Free[idx] = 0;
    70. }
    71. return var - row;
    72. }
    73. for (int i = var - 1; i >= 0; i--)
    74. {
    75. temp = a[i][var];
    76. for (int j = i + 1; j < var; j++)
    77. {
    78. if (a[i][j])
    79. temp -= a[i][j] * ans[j];
    80. }
    81. ans[i] = temp / a[i][i];
    82. }
    83. return 0;
    84. }

    (3)、整数类型解

    1. int a[maxn][maxn];
    2. int ans[maxn];
    3. int Free[maxn];
    4. int GCD(int a, int b)
    5. {
    6. if (!b)
    7. return a;
    8. return GCD(b, a % b);
    9. }
    10. int LCM(int a, int b)
    11. {
    12. return a / GCD(a, b) * b;
    13. }
    14. int Fabs(int x)
    15. {
    16. if (x < 0)
    17. return -x;
    18. return x;
    19. }
    20. int Gauss(int equ, int var)
    21. {
    22. for (int i = 0; i <= var; i++)
    23. {
    24. ans[i] = 0;
    25. Free[i] = 1;
    26. }
    27. int row, col, MaxRow;
    28. col = 1;
    29. for (row = 1; row <= equ && col < var; row++, col++)
    30. {
    31. MaxRow = row;
    32. for (int i = row + 1; i <= equ; i++)
    33. {
    34. if (Fabs(a[i][col]) > Fabs(a[MaxRow][col]))
    35. MaxRow = i;
    36. }
    37. if (MaxRow != row)
    38. {
    39. for (int i = row; i <= var; i++)
    40. swap(a[row][i], a[MaxRow][i]);
    41. }
    42. if (!a[row][col])
    43. {
    44. row--;
    45. continue;
    46. }
    47. for (int i = row + 1; i <= equ; i++)
    48. {
    49. if (a[i][col])
    50. {
    51. int lcm = LCM(Fabs(a[i][col]), Fabs(a[row][col]));
    52. int T1 = lcm / Fabs(a[i][col]);
    53. int T2 = lcm / Fabs(a[row][col]);
    54. if (a[i][col] * a[row][col] < 0)
    55. T2 = -T2;
    56. for (int j = col; j <= var; j++)
    57. a[i][j] = a[i][j] * T1 - a[row][j] * T2;
    58. }
    59. }
    60. }
    61. for (int i = row; i <= equ; i++)
    62. {
    63. if (a[i][col])
    64. return -1;
    65. }
    66. int temp;
    67. if (row < var)
    68. {
    69. return var - row;
    70. }
    71. for (int i = var - 1; i > 0; i--)
    72. {
    73. temp = a[i][var];
    74. for (int j = i + 1; j < var; j++)
    75. {
    76. if (a[i][j])
    77. temp -= a[i][j] * ans[j];
    78. }
    79. ans[i] = temp / a[i][i];
    80. }
    81. return 0;
    82. }

    (4)、模线性方程组

    1. int a[maxn][maxn];
    2. int Gauss(int equ, int var)
    3. {
    4. int row, col = 0;
    5. for (row = 0; row < equ && col < var; row++, col++)
    6. {
    7. int MaxRow = row;
    8. for (int i = row + 1; i < equ; i++)
    9. {
    10. if (abs(a[i][col]) > abs(a[MaxRow][col]))
    11. MaxRow = i;
    12. }
    13. if (row != MaxRow)
    14. {
    15. for (int i = row; i <= var; i++)
    16. swap(a[row][i], a[MaxRow][i]);
    17. }
    18. if (!a[row][col])
    19. {
    20. row--;
    21. continue;
    22. }
    23. for (int i = row + 1; i <= equ; i++)
    24. {
    25. if (a[i][col])
    26. {
    27. int T = a[i][col] * q_pow(a[row][col], mod - 2, mod) % mod;
    28. for (int j = col; j <= var; j++)
    29. a[i][j] = (a[i][j] - a[row][j] * T % mod + mod) % mod;
    30. }
    31. }
    32. }
    33. for (int i = row; i <= equ; i++)
    34. {
    35. if (a[i][col])
    36. return -1;
    37. }
    38. if (row < var)
    39. return var - row;
    40. for (int i = var - 1; i >= 0; i--)
    41. {
    42. int temp = a[i][var];
    43. for (int j = i + 1; j < var; j++)
    44. {
    45. if (a[i][j])
    46. {
    47. temp -= a[i][j] * x[j];
    48. temp = (temp % mod + mod) % mod;
    49. }
    50. }
    51. x[i] = temp * q_pow(a[i][i], mod - 2, mod) % mod;
    52. }
    53. return 0;
    54. }

    二、线性基

    1、线性基是一个数的集合,并且每个序列都拥有至少一个线性基,取线性基中若干个数异或起来可以得到原序列中的任何一个数

    2、线性基的构造

    1. int d[maxn];
    2. void add(ll x)
    3. {
    4. for (int i = 60; i >= 0; i--)
    5. {
    6. if (x & (1ll << i))//注意,如果i大于31,前面的1的后面一定要加ll
    7. {
    8. if (d[i])x ^= d[i];
    9. else
    10. {
    11. d[i] = x;
    12. break;//插入成功就退出
    13. }
    14. }
    15. }
    16. }

  • 相关阅读:
    ModStart : 宝塔配置MySQL队列调度
    L4W3作业 自动驾驶 - 车辆识别
    C++容器之unordered_map、unordered_set的底层剖析
    linux(1.nginx基础 && 2.使用Nginx负载均衡及动静分离)
    FOC学习笔记-坐标变换以及仿真验证
    v-bind指令:设置元素的属性
    人工智能学习:CIFAR-10数据分类识别
    数据可视化图表之面积折线图
    牛客算法課 (算法入門班) 二分, 三分, 01分數規劃
    4.6版本Wordpress漏洞复现
  • 原文地址:https://blog.csdn.net/qq_62751626/article/details/125508458