我在努力改进我的算法,但没有进展。
我需要一个可重用的函数来计算x*3+y*5=n
。
约束条件:
n>=7
x,y,n始终为正整数
我需要找到x和y之间最短距离的组合
(绝对值)|x-y|
这是我编写的一个控制台应用程序草稿,它可以编译和工作,但正如您所见,在处理大量数据时效率很低。
我认为我缺乏数学知识来改进代码:
static void Main(string[] args)
{
GetWarAfterMath(5000000);
Console.ReadLine();
}
const int FIRST = 3;
const int SECOND = 5;
static void GetWarAfterMath(int n)
{
int x = 0;
int y = 0;
int delta = 0;
int i = 0;
int j = 0;
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
{
if ((i * FIRST) + (j * SECOND) == n)
{
// Console.WriteLine(i + "*" + FIRST + "+" + j + "*" + SECOND + "=" + n);
if (Math.Abs(i - j) < delta)
{
x = i;
y = j;
delta = Math.Abs(x - y);
}
break;
}
else if ((j * FIRST) + (i * SECOND) == n)
{
// Console.WriteLine(j + "*" + FIRST + "+" + i + "*" + SECOND + "=" + n);
if (j - i < delta)
{
x = j;
y = i;
delta = Math.Abs(x - y);
}
break;
}
}
}
Console.WriteLine("THE WINNERS ARE:" + x + "*" + FIRST + "+" + y + "*" + SECOND + "=" + n);
}
编辑:
最后,在将@yves daoost、@user3386109和@hasson组合在一起之后。
时间复杂度急剧下降,执行时间为8000000:127毫秒!
这是最后一个算法:
static void Main(string[] args)
{
GetMatch(34);
Console.ReadLine();
}
const double FIRST = 3;
const double SECOND = 5;
static void GetMatch(double n)
{
int x = 0;
int y = 0;
int finalX = 0;
int finalY = int.MaxValue;
for (int i = 0; i < n / FIRST; i++)
{
if (((n - FIRST * i) / SECOND) % 1 == 0)
{
y = Convert.ToInt32(((n - FIRST * i) / SECOND));
x = i;
if(Math.Abs(x-y) < Math.Abs(finalX-finalY))
{
finalX = x;
finalY = y;
}
}
}
Console.WriteLine("THE WINNERS ARE:" + finalX + "*" + FIRST + "+" + finalY + "*" + SECOND + "=" + n + " Calc: " + (finalX * FIRST + finalY * SECOND));
}
请注意,正如@Yves daoost在他的第一个答案中所写的那样,使用欧几里得算法用inear丢番图方程来解决这个问题也是可能的,但是您需要反向使用欧几里得算法,我宁愿保持它的简单性。
如果有人感兴趣的话,这里有一个关于这个主题的很好的视频和一个解决方案:
数论:Diophantine Equation: ax+by=gcd(a,b)
非常感谢你的帮助。
最佳答案
这个问题在数论中很有名(它是一个线性丢番图方程)。
只有当ax+by = c
时,它才能有一个解决方案,这当然总是正确的。
然后,如果您知道一些gcd(3,5)|n
的解决方案,所有的解决方案都是3x°+5y°=n
,x=x°-5k
格式的。
很容易找到解决方案,因为y=y°+3k
,n
,n-5
中的一个肯定是n-10
的倍数。
剩下的就是在约束条件下最小化3
,|x°-5k-y°-3k|
。最小值将通过最接近x°-5k>0
的值y°+3k>0
或使其中一个约束饱和的值来实现。
例如,For8k
,x°-y°
和n=173000
是一个解决方案然后x°=57665
产生y°=1
此解决方案是可接受的,因为已满足约束。
我没有提供案例研究的全部细节,但主要教训是:不需要循环!