递归和无递归得到不同的答案

时间:2019-05-07 16:09:53

标签: c recursion

对不起,我的母语不是英语。

家庭作业是关于计算模量。红利是如此之大(a ^ y,a和y可能是10 ^ 18),所以我应该使用公式:(m * n)%d =(m%d * n%d)%d来完成该操作。

所以我的逻辑如下:

如果y = 0,则返回1%d

如果y = 1,则返回a%d

如果y是偶数,则返回递归并让m = n = a ^(y / 2)

如果y为奇数,则返回递归并让m = x ^(y-1)n = a

问题是:因为y是奇数,所以有两种方法可以解决x:

  • 1:直接计算(a%d)

  • 2:使用递归,功效为1

您可以在下面看到我的代码。在~~ ~~中,如果填写“ a%d”是正确的,但“ remain(1)”是错误的。

但只有方法1的答案是正确的。

在也使用方法1的情况下也可以获得正确的答案。我仍然想知道为什么使用方法2是错误的? 那么如何使用方法2解决问题呢?如果可以,我应该如何修改代码?我不能,为什么?

我曾尝试使用2种不同的方法以任何递归方式打印子答案。我看到方法2在y为奇数时,其子答案是错误的,它可能会返回负值。

这是我的代码如下:

X

如果输入16777215 16777215 23842982

方法1的答案是6647725(正确)。

方法2的答案是12467225(错误)。

TA,我不知道为什么方法2是错误的。我的助教建议我在这里问这个问题。非常感谢。

2 个答案:

答案 0 :(得分:4)

remain()必须定义为long long int。 拥有的方式是,在这里将两个int相乘并观察到整数溢出:

else if(y%2==1) return ((remain(y-1))*(remain(1)))%d;

我已检查:将定义固定为

long long int remain(long long int y)

我得到了预期的结果

顺便说一句。您可能会看到启用了编译器警告的情况,因为printf()会引起编译器警告(至少gcc会这样做)

答案 1 :(得分:0)

我猜您正在溢出使用的类型。也许int64_t remain(int64_t y);可以工作。

我将使用更广泛的类型并修复代码样式,以便您了解如何正确编码。我还将使用固定宽度的整数,这是您在99%的时间内应该使用的整数(除非有充分的理由不这样做)。

#include <inttypes.h>
#include <stdint.h>
#include <stdio.h>


int64_t a, i, d;


int64_t remain(int64_t y)
{
        int64_t temp;

        if (!y)
                return 1 % d;
        if (y == 1)
                return a % d;
        if (!(y % 2)) {
                temp = remain(y / 2);
                return (temp * temp) % d;
        }
        return (remain(y - 1) * remain(1)) % d;
}


int main(void)
{

        scanf("%"SNCi64" %"SCNi64" %"SCNi64"", &a, &i, &d);
        printf("%"PRIi64"\n", remain(i));

        return 0;
}

我没有解决诸如使用全局变量之类的问题,但您应该这样做。