藍橋杯---貌似化學---逆矩陣

試題 算法訓練 貌似化學

資源限制

  時間限制:1.0s 內存限制:256.0MB

問題描述

  現在有a,b,c三種原料,如果他們按x:y:z混合,就能產生一種神奇的物品d。
  當然不一定只產生一份d,但a,b,c的最簡比一定是x:y:z
  現在給你3種可供選擇的物品:
  每個物品都是由a,b,c以一定比例組合成的,求出最少的物品數,使得他們能湊出整數個d物品(這裏的最少是指三者個數的總和最少)

輸入格式

  第一行三個整數,表示d的配比(x,y,z)
  接下來三行,表示三種物品的配比,每行三個整數(<=10000)。

輸出格式

  四個整數,分別表示在最少物品總數的前提下a,b,c,d的個數(d是由a,b,c配得的)
  目標答案<=10000
  如果不存在滿足條件的方案,輸出NONE

樣例輸入

3 4 5
1 2 3
3 7 1
2 1 2

樣例輸出

8 1 5 7

實現思路

假設已經知道了答案x, y , z;
存在這樣的關係
(x y z)(a1b1c1a2b2b3a2b2b3)=(a b c) (x \ y \ z) * \begin{pmatrix} a1 & b1 & c1 \\ a2 &b2 & b3 \\ a2 &b2 & b3 \end{pmatrix} = (a \ b \ c)
那麼 (x y z) 其實就可以通過逆矩陣求得
(x y z)=(a b c)(a1b1c1a2b2b3a2b2b3)1 (x \ y \ z) = (a \ b \ c) * \begin{pmatrix} a1 & b1 & c1 \\ a2 &b2 & b3 \\ a2 &b2 & b3 \end{pmatrix} ^{-1}

實現代碼

#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;

typedef long long ll;

ll a[4][4], b[3][3], c[3], d[3];

ll gcd(ll a, ll b) { // 歐幾里得求解最大公因子
	if (a < b) swap(a, b);
	if (b == 0) return a;
	else return gcd(b, a % b);
}

void count() {
	// 求逆矩陣
	for (int i = 0; i < 3; i++) { 
		for (int j = 0; j < 3; j++) {
			int minc, maxc, minr, maxr;
			minc = min((i + 1) % 3, (i + 2) % 3), maxc = max((i + 1) % 3, (i + 2) % 3);
			minr = min((j + 1) % 3, (j + 2) % 3), maxr = max((j + 1) % 3, (j + 2) % 3);
			b[i][j] = pow (-1, i + j) * (a[minr][minc] * a[maxr][maxc] - a[maxr][minc] * a[minr][maxc]);
		}
	}
	//求解待解矩陣
	for (int i = 0; i < 3; i++) d[i] = b[0][i] * c[0] + b[1][i] * c[1] + b[2][i] * c[2];
	if (d[0] < 0 || d[1] < 0 || d[2] < 0) d[0] = -d[0], d[1] = -d[1], d[2] = -d[2];
	if (d[1] < 0 || d[2] < 0) cout << "NONE" << endl; // 若存在不同號,則現實中不存在負數的量,即不存在
	else {
		ll temp = gcd(d[0], d[1]); temp = gcd(temp, d[2]);
		ll ans = 0;
		for (int i = 0; i < 3; i++) d[i] /= temp;
		for (int i = 0; i < 3; i++) ans += d[i] * a[i][0];
		ans /= c[0];
		cout << d[0] << " " << d[1] << " " << d[2] << " " << ans << endl;
	}
}

int main() { 
	for (int i = 0; i < 3; i++) cin >> c[i];
	for (int i = 0; i < 3; i++) for (int j = 0; j < 3; j++) cin >> a[i][j];
	count();
	return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章