算法训练 貌似化学
时间限制:1.0s 内存限制:512.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
分析:设a, b, c, d四种物品的个数分别为,给定的三种物品的配比分别为
(即对应输入的第2~4行)
于是可以列出三元一次方程组
现要求出使得均为正整数的最小的
。
#include <stdio.h>
long long int det(long long int mat[3][3])
{
return mat[0][0] * mat[1][1] * mat[2][2] +
mat[1][0] * mat[2][1] * mat[0][2] +
mat[2][0] * mat[0][1] * mat[1][2] -
mat[2][0] * mat[1][1] * mat[0][2] -
mat[1][0] * mat[0][1] * mat[2][2] -
mat[0][0] * mat[2][1] * mat[1][2];
}
int solve(long long int A[3][3], long long int d[3], long long int *x, long long int *y, long long int *z)
{
long long int delta = det(A);
long long int delta_x, delta_y, delta_z;
for (int k = 0; k < 3; ++k)
{
long long int A_rep[3][3] = { 0 };
for (int j = 0; j < 3; ++j)
{
if (j == k)
{
for (int i = 0; i < 3; ++i)
A_rep[i][j] = d[i];
}
else
{
for (int i = 0; i < 3; ++i)
A_rep[i][j] = A[i][j];
}
}
if (k == 0)
{
delta_x = det(A_rep);
if (delta_x % delta != 0)
return 0;
*x = delta_x / delta;
if (*x < 0)
return 0;
}
else if (k == 1)
{
delta_y = det(A_rep);
if (delta_y % delta != 0)
return 0;
*y = delta_y / delta;
if (*y < 0)
return 0;
}
else
{
delta_z = det(A_rep);
if (delta_z % delta != 0)
return 0;
*z = delta_z / delta;
if (*z < 0)
return 0;
}
}
return 1;
}
int main()
{
long long A[3][3] = { 0 }, d[3] = { 0 };
long long int x, y, z;
long long int na, nb, nc, nd;
scanf("%lld %lld %lld", &x, &y, &z);
for (int j = 0; j < 3; ++j)
for (int i = 0; i < 3; ++i)
scanf("%lld", &A[i][j]);
if (det(A) == 0)
{
printf("NONE");
return 0;
}
for (nd = 1; nd <= 10000; ++nd)
{
d[0] = nd * x;
d[1] = nd * y;
d[2] = nd * z;
if (solve(A, d, &na, &nb, &nc))
{
printf("%lld %lld %lld %lld", na, nb, nc, nd);
return 0;
}
}
printf("NONE");
return 0;
}