朋友问我:
如果2^10 = 1024
,我们可以取1024并打破并汇总其数字:
1+0+2+4 = 7.
这很容易。
但是当输入为2^30000
时(输入实际上是一个长字符串"1000..."
) - 没有.net类型可以保存此值。
所以必须有一个技巧来加总其数字(小数值的数字)....
已编辑:
相关技巧(用于查找10^20 - 16
)
100 = 10 ^ 2(一个和两个零)
10 ^ 20 =(1和20个零)
因此:
10 ^ 20 - 16 = 18个9,8个和4个。
18 * 9 + 8 + 4 = 174
但我没有成功将此解决方案转换为我的问题。(我尝试了很多)。
*我将此问题标记为.net,因为我可以使用字符串函数,来自.net库的数学函数。*
问题
这里有什么技巧可以让我总结很多数字,这是x^n
的结果吗?
这里的诀窍是什么?
编辑#2 :添加.net2标记(biginteger不可用) - 我想知道如何在没有biginteger的情况下做到这一点。(我正在寻找隐藏的技巧)
答案 0 :(得分:7)
您可以利用BigInteger结构来执行此操作。因为它是用MSDN编写的
BigInteger类型是一个表示一个的不可变类型 任意大整数,其理论上的值没有上限或下限 界限。
基本上在创建BigInteger实例并评估指数后,您可以将其转换为字符串。之后,您将遍历该字符串的每个字符,并将每个char转换为int数。添加所有这些int数字,你就会得到答案。
BigInteger bi = new BigInteger(2);
var bi2 = BigInteger.Pow(bi, 30000);
BigInteger sum = new BigInteger();
foreach(var ch in bi2.ToString())
sum = BigInteger.Add(sum, new BigInteger(int.Parse(ch.ToString())));
MessageBox.Show(bi2.ToString() + " - " + sum.ToString());
答案 1 :(得分:5)
我不知道找到一个数字的基数10位数和的一般技巧。
但是,有一个简单的方法可以找到一个数字的基数10位根。
正如您所说,数字总和只是所有数字的总和。 1024的基数10位是1 + 2 + 4 = 7.基数10位数和65536是6 + 5 + 5 + 3 + 6 = 25.
数字根是重复数字总和时得到的,直到只有一个数字。数字总和65536是25,因此数字根是2 + 5 = 7.
技巧是:如果你有Z = X * Y,那么DigitRoot(Z)= DigitRoot(DigitRoot(X)* DigitRoot(Y))。 (向读者练习:证明它!提示:首先证明添加相同的身份。)
如果你有一个易于分解的数字 - 并且最简单的因子是2 n - 那么很容易递归地找出数字根:2 16 = 2 8 * 2 8 ,因此DigitRoot(2 16 )= DigitRoot(DigitRoot(2 8 ) * DigitRoot(2 8 )) - 我们只是把问题变得更小了。现在我们不必计算2 16 ,我们只需要计算2 8 。您当然可以使用2 30000 - 将其分解为DigitRoot(DigitRoot(2 15000 * DigitRoot(2 15000 ))如果2 15000 太大,请将其进一步分解;继续将其分解,直到遇到足够小的问题解决。
有意义吗?
答案 2 :(得分:2)
我不相信这里可以有一招。 你显示的后一个技巧是有效的,因为数字和结果都是十进制数。
For example:
1267 = 1*10^3 + 2*10^2 + 6*10^1 + 7*10^0
所以你的权力与总和之间存在明显的相关性。 但不幸的是,如果你想将二进制数或2的幂转换成十进制数,那就不行了。尽最大努力减少增加基数的能力。
2^3000 = 4^1500 = 16^750 = 256^375
但是正如你所看到的那样,系列跳过基数10.这很遗憾地意味着你需要将最终结果计算为十进制数,然后才能将其转换为10的幂。使这个技巧无效。
答案 3 :(得分:1)
来自http://blog.singhanuvrat.com/problems/sum-of-digits-in-ab:
public class Problem_16 {
public long sumOfDigits(int base, int exp) {
int numberOfDigits = (int) Math.ceil(exp * Math.log10(base));
int[] digits = new int[numberOfDigits];
digits[0] = base;
int currentExp = 1;
while (currentExp < exp) {
currentExp++;
int carry = 0;
for (int i = 0; i < digits.length; i++) {
int num = base * digits[i] + carry;
digits[i] = num % 10;
carry = num / 10;
}
}
long sum = 0;
for (int digit : digits)
sum += digit;
return sum;
}
public static void main(String[] args) {
int base = 2;
int exp = 3000;
System.out.println(new Problem_16().sumOfDigits(base, exp));
}
}
C#
public class Problem_16 {
public long sumOfDigits(int base1, int exp) {
int numberOfDigits = (int) Math.Ceiling(exp * Math.Log10(base1));
int[] digits = new int[numberOfDigits];
digits[0] = base1;
int currentExp = 1;
while (currentExp < exp) {
currentExp++;
int carry = 0;
for (int i = 0; i < digits.Length; i++) {
int num = base1 * digits[i] + carry;
digits[i] = num % 10;
carry = num / 10;
}
}
long sum = 0;
foreach (int digit in digits)
sum += digit;
return sum;
}
}
void Main()
{
int base1 = 2;
int exp = 3000000;
Console.WriteLine (new Problem_16().sumOfDigits(base1, exp));
}