Tam*_*s F 9 c# math numbers number-theory
所以我有一个整数,例如1234567890和一组给定的数字,例如{4,7,18,32,57,68}
问题是1234567890是否可以由给定的数字组成(您可以使用多个数字,而不必使用所有数字).在上面的情况中,一种解决方案是:
38580246*32 + 1*18
(不需要提供具体的解决方案,只有在可以完成的情况下)
我的想法是尝试所有解决方案.例如,我会尝试
1*4*+ 0*7 + 0*18 + 0*32 + 0*57 + 0*68 = 4
2*4*+ 0*7 + 0*18 + 0*32 + 0*57 + 0*68 = 8
3*4*+ 0*7 + 0*18 + 0*32 + 0*57 + 0*68 = 12
.....
308 641 972*4*+ 0*7 + 0*18 + 0*32 + 0*57 + 0*68 = 1234567888
308 641 973*4*+ 0*7 + 0*18 + 0*32 + 0*57 + 0*68 = 1234567892 ==>超过
0*4*+ 1*7 + 0*18 + 0*32 + 0*57 + 0*68 = 7
1*4*+ 1*7 + 0*18 + 0*32 + 0*57 + 0*68 = 11
2*4*+ 1*7 + 0*18 + 0*32 + 0*57 + 0*68 = 15
等等......
这是我在c#中的代码:
static int toCreate = 1234567890;
static int[] numbers = new int[6] { 4, 7, 18, 32, 57, 68};
static int[] multiplier;
static bool createable = false;
static void Main(string[] args)
{
multiplier = new int[numbers.Length];
for (int i = 0; i < multiplier.Length; i++)
multiplier[i] = 0;
if (Solve())
{
Console.WriteLine(1);
}
else
{
Console.WriteLine(0);
}
}
static bool Solve()
{
int lastIndex = 0;
while (true)
{
int comp = compare(multiplier);
if (comp == 0)
{
return true;
}
else if (comp < 0)
{
lastIndex = 0;
multiplier[multiplier.Length - 1]++;
}
else
{
lastIndex++;
for (int i = 0; i < lastIndex; i++)
{
multiplier[multiplier.Length - 1 - i] = 0;
}
if (lastIndex >= multiplier.Length)
{
return false;
}
multiplier[multiplier.Length - 1 - lastIndex]++;
}
}
}
static int compare(int[] multi)
{
int osszeg = 0;
for (int i = 0; i < multi.Length; i++)
{
osszeg += multi[i] * numbers[i];
}
if (osszeg == toCreate)
{
return 0;
}
else if (osszeg < toCreate)
{
return -1;
}
else
{
return 1;
}
}
Run Code Online (Sandbox Code Playgroud)
代码工作正常(据我所知)但速度太慢.解决该示例需要大约3秒,并且可能有100个数字来自100个数字.
我有一个递归解决方案。它在大约 0.005 秒内解决了 OP 的原始问题(在我的机器上)并告诉您计算结果。
private static readonly int Target = 1234567890;
private static readonly List<int> Parts = new List<int> { 4, 7, 18, 32, 57, 68 };
static void Main(string[] args)
{
Console.WriteLine(Solve(Target, Parts));
Console.ReadLine();
}
private static bool Solve(int target, List<int> parts)
{
parts.RemoveAll(x => x > target || x <= 0);
if (parts.Count == 0) return false;
var divisor = parts.First();
var quotient = target / divisor;
var modulus = target % divisor;
if (modulus == 0)
{
Console.WriteLine("{0} X {1}", quotient, divisor);
return true;
}
if (quotient == 0 || parts.Count == 1) return false;
while (!Solve(target - divisor * quotient, parts.Skip(1).ToList()))
{
if (--quotient != 0) continue;
return Solve(target, parts.Skip(1).ToList());
}
Console.WriteLine("{0} X {1}", quotient, divisor);
return true;
}
Run Code Online (Sandbox Code Playgroud)
基本上,它会遍历每个数字,看看在给定当前商和数字的情况下是否有可能的解决方案“低于”它。如果不存在,则从商中减去 1,然后重试。它会执行此操作,直到用尽该数字的所有选项,然后转到下一个数字(如果可用)。如果所有数字都用尽,则无解。