problem statement要求我查找^ b的最后一位数字。 约束是0 <= a <= 20且0 <= b <= 2,147,483,000。
我的代码适用于12 ^ 8或6 ^ 9或类似的数字。 但是当我移动到大数字区域时,例如14 ^ 1234或17 ^ 148713,我总是得到-8的输出。
#include <stdio.h>
#include <math.h>
int main() {
int t;
scanf("%d", &t);
while(t--)
{
int a;
long long int b;
double x, y, res;
scanf("%d %lld", &a, &b);
x=(double)a;
y=(double)b;
res = pow(x, y);
int rem;
rem = (int)res%10;
printf("%d\n", rem);
}
return 0; }
这种奇怪的输出可能是什么原因?
除了将大数字存储在数组中之外没有办法解决(我想像How to calculate 2 to the power 10000000这样的东西)?
答案 0 :(得分:1)
int
可以保存最多包含2 ^ 31 - 1的值,因此您基本上有溢出(实际上它导致未定义行为与溢出无符号类型相反)。
正如@PaulR在对您的问题的评论中已经指出的那样,一般的想法是滥用模幂运算的某些属性。简而言之:您需要保持数字“足够小”以防止防止溢出并能够获得所需的结果。
我们可以使用以下属性:(a * b) % m == (a % m) * (b % m)
。在代码中它看起来像这样:
const unsigned int m = 10; // our modulus
while(t--)
{
... // read 'a' and 'b'
unsigned int res = 1; // last digit of a^b (e.g. res == (a^b % m))
for (unsigned int i = 0; i < b; ++i)
{
res *= a; // rising to power i
res %= m; // keep res small !
}
... // you get desired result
}
注意:将a
和b
声明为unsigned int
- 这对您的限制就足够了,可以防止签名和无符号之间的无关和无意转换。
答案 1 :(得分:0)
请参阅Integer Overflow了解为什么它是负数,至于为什么值总是-8,那么比我聪明的人会回答那个。