【exgcd】“范式杯”2023牛客暑期多校训练营1 M
发布人:shili8
发布时间:2025-01-16 02:32
阅读次数:0
**范式杯**2023 牛客暑期多校训练营**一、题目描述**
在一个 $n times m$ 的矩阵中,给定一个矩阵 $A$ 和一个向量 $b$。要求找到满足方程 $Ax = b$ 的解。
**二、输入输出格式**
* 输入:两个整数 $n, m$,表示矩阵 $A$ 的行数和列数;接下来是 $nm$ 个整数,表示矩阵 $A$ 的元素;最后一个整数 $k$,表示向量 $b$ 中的元素个数;接下来是 $k$ 个整数,表示向量 $b$ 的元素。
* 输出:如果有解,则输出满足方程 $Ax = b$ 的解 $x$;否则输出 "-1"。
**三、代码实现**
cpp#include <iostream> #include <vector> using namespace std; const int N =2e5 +10; typedef long long ll; ll n, m, k; ll a[N], b[N]; void exgcd(ll a, ll b, ll &x, ll &y) { if (!b) { x =1; y =0; return; } exgcd(b, a % b, y, x); y -= (a / b) * x; } void solve() { cin >> n >> m; for (ll i =1; i <= n * m; ++i) { cin >> a[i]; } ll ans =0; for (ll i =1; i <= k; ++i) { cin >> b[i]; ans += b[i] * a[i]; } if (!ans) { cout << "-1 "; return; } exgcd(n, m, n, m); ll x = (ll)((-b[1]) % n + n) % n; for (int i =2; i <= k; ++i) { b[i] += b[i -1] * x; if (b[i] >= n) { b[i] -= n; } } cout << x << " "; for (ll i =2; i <= k; ++i) { cout << b[i] << " "; } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int T =1; while (T--) { solve(); } return0; }
**四、注释**
* 本题要求找到满足方程 $Ax = b$ 的解。
* 我们首先使用扩展欧几里得算法(exgcd)来求出矩阵 $A$ 和向量 $b$ 的最大公约数,并且得到一个整数系 $(x, y)$,使得 $ax + by = gcd(a, b)$。
* 然后,我们使用这个整数系来求解方程 $Ax = b$。具体来说,我们首先将向量 $b$ 中的每个元素都加上一个倍数,使得所有元素都是非负整数,然后我们可以直接输出这些元素作为解。
**五、时间复杂度**
* 时间复杂度为 O(n + m)。
**六、空间复杂度**
* 空间复杂度为 O(1)。