找到号码
本文关键字:号码 | 更新日期: 2023-09-27 18:18:15
这是一个问题陈述。
假设一个数字2345。如果把它的数字相乘,就得到120。现在,如果你再乘以120,你会得到数字0,这是一个一位数。如果我把2345的数字加起来,就得到14。如果我把14的数字加起来,就会得到5,这是一个一位数。
因此,任何数都可以在一定步数内转换为两个个位数。你可以看到2345通过两步的数字乘法被转换为0,通过两步的数字加法被转换为5。现在考虑任意数字n,假设它可以通过n1步将数字乘以一个数字d1,并通过n2步将数字加到一个数字d2来转换。
你的任务是找到大于N且小于1000000000的最小数字,该数字可以在小于或等于n1步的时间内乘以d1,并在小于或等于n2步的时间内将其数字与d2相加。
我认为你只是错误地处理/解释了这个问题;这是暗箱操作:
using System;
using System.Diagnostics;
static class Program
{
static void Main()
{
// check our math first!
// You can see 2345 is converted to 0 by using multiplication of digits in 2 steps
int value, steps;
value = MultiplyToOneDigit(2345, out steps);
Debug.Assert(value == 0);
Debug.Assert(steps == 2);
// and it is converted to 5 by using addition of digits in 2 steps
value = SumToOneDigit(2345, out steps);
Debug.Assert(value == 5);
Debug.Assert(steps == 2);
// this bit is any random number
var rand = new Random();
for (int i = 0; i < 10; i++)
{
int N = rand.Next(0, MAX);
int result = Execute(N);
Console.WriteLine("For N={0}, our answer is {1}", N, result);
}
}
const int MAX = 1000000000;
//Now consider any number N.
static int Execute(int N)
{
// Let us say that it can be converted by multiplying digits to a one digit number d1 in n1
// steps and by adding digits to one digit number d2 in n2 steps.
int n1, n2;
int d1 = MultiplyToOneDigit(N, out n1),
d2 = SumToOneDigit(N, out n2);
// Your task is to find smallest number greater than N and less than 1000000000
for (int i = N + 1; i < MAX; i++)
{
int value, steps;
// which can be converted by multiplying its digits to d1 in less than or equal to n1 steps
value = MultiplyToOneDigit(i, out steps);
if (value != d1 || steps > n1) continue; // no good
// and by adding its digits to d2 in less than or equal to n2 steps.
value = SumToOneDigit(i, out steps);
if(value != d2 || steps > n2) continue; // no good
return i;
}
return -1; // no answer
}
static int MultiplyToOneDigit(int value, out int steps)
{
steps = 0;
while (value > 10)
{
value = MultiplyDigits(value);
steps++;
}
return value;
}
static int SumToOneDigit(int value, out int steps)
{
steps = 0;
while (value > 10)
{
value = SumDigits(value);
steps++;
}
return value;
}
static int MultiplyDigits(int value)
{
int acc = 1;
while (value > 0)
{
acc *= value % 10;
value /= 10;
}
return acc;
}
static int SumDigits(int value)
{
int total = 0;
while (value > 0)
{
total += value % 10;
value /= 10;
}
return total;
}
}
我可以看到两个内存问题;第一个是生成大量字符串——你可能想这样处理:
static int SumDigits(int value)
{
int total = 0;
while (value > 0)
{
total += value % 10;
value /= 10;
}
return total;
}
(即完全未测试)
第二个问题是庞大的列表;你不需要存储(在lstString
中)每个值只是为了找到最小值。记录下你到目前为止做得最好的。或者,如果需要每个值的数据,那么:不要将它们存储为string
。实际上,i
无论如何都可以隐含(从列表/数组中的位置),因此您真正需要的是每个值的cnt
值的int[]
。int[1000000000]
本身是4GB,所以在最近的。net版本(<gcAllowVeryLargeObjects>
)中需要大数组支持。但更好的做法是:不要存储它。
但是它抛出了
System.OutOfMemoryException
。
这仅仅意味着内存不足。您的限制是1,000,000,000
或大约1G。对于32位系统来说已经太大的字符串引用乘以4字节。即使没有实际的字符串。
你可以将答案更紧凑地存储在int[]
数组中,但这仍然会显示相同的问题。
所以,降低你的限制或者编译并在64位PC上运行
A for effort:)
现在一起做。你当然可以做重构。
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace _17082903_smallest_greatest_number
{
class Program
{
static void Main(string[] args)
{
int N = 2344;
int n1 = 0;
int n2 = 0;
int d1 = SumDigits(N, ref n1);
int d2 = ProductDigits(N, ref n2);
bool sumFound = false, productFound = false;
for (int i = N + 1; i < 1000000000; i++)
{
if (!sumFound)
{
int stepsForSum = 0;
var res = SumDigits(i, ref stepsForSum);
if (res == d1 && stepsForSum <= n1)
{
Console.WriteLine("the smallest number for sum is: " + i);
Console.WriteLine(string.Format("sum result is {0} in {1} steps only", res, stepsForSum));
sumFound = true;
}
stepsForSum = 0;
}
if (!productFound)
{
int stepsForProduct = 0;
var res2 = ProductDigits(i, ref stepsForProduct);
if (res2 == d2 && stepsForProduct <= n2)
{
Console.WriteLine("the smallest number for product is: " + i);
Console.WriteLine(string.Format("product result is {0} in {1} steps only", res2, stepsForProduct));
productFound = true;
}
stepsForProduct = 0;
}
if (productFound && sumFound)
{
break;
}
}
}
static int SumDigits(int value, ref int numOfSteps)
{
int total = 0;
while (value > 0)
{
total += value % 10;
value /= 10;
}
numOfSteps++;
if (total < 10)
{
return total;
}
else
{
return SumDigits(total, ref numOfSteps);
}
}
static int ProductDigits(int value, ref int numOfSteps)
{
int total = 1;
while (value > 0)
{
total *= value % 10;
value /= 10;
}
numOfSteps++;
if (total < 10)
{
return total;
}
else
{
return ProductDigits(total, ref numOfSteps);
}
}
}
}