为什么我的功能不能用于大数字?我怎样才能更改它?

时间:2015-11-01 18:47:04

标签: c++ modulo

我找到了一个解决问题的公式,但我不能让它适用于大数字。第n个因子是第(n-1)个因子+(n-1)*(n-1)+ n * n

所以我写了这个函数:

inline long long int formula(long long int n)
{
    if(n==1)return 1;
    return formula(n-1)+(n-1)*(n-1)+*n*n;
}

因为答案必须以666013为模计算,所以我添加了这个(MOD = 666013):

inline long long int formula(long long int n)
{
    if(n==1)return 1;
    return ((formula(n-1)%MOD+(1LL*(n-1)*(n-1))%MOD)%MOD+(1LL*n*n)%MOD)%MOD;
}

我可能没有正确使用模数。我的功能必须适用于大到2.000.000.000的数字,并且它停止工作在大约30.000

编辑:我尝试过使用循环,但仍然无法使其适用于大于20.000.000的数字。这就是我正在使用的:

ans=1;
    for(i=2;i<=n;i++)
    {
        ans=(ans%MOD+1LL*(i-1)*(i-1)%MOD+1LL*i*i%MOD)%MOD;
    }

4 个答案:

答案 0 :(得分:3)

我不明白你为什么要使用递归函数。它可以在少量的呼叫中工作,但是如果你递归地称它为几百万次,那么......它不会。原因是你在另一个函数中调用另一个函数中的函数...太多次激发程序崩溃或命名为&#34; Stack Overflow&#34;。

克服这种情况的最佳方法是使用循环来修复它!只需从0迭代到n(n是您想要获得的数字)。

答案 1 :(得分:2)

尽可能简化以便能够查看要求:

typedef long long val_t;
#define MOD         ((val_t) 666013)

// for really big numbers, change #if to 1
#if 0
#define MODOF(_x)   ((_x) % MOD)
#else
#define MODOF(_x)   (_x)
#endif

#define SQR(_i)     MODOF((_i) * (_i))

val_t
formula(val_t n)
{
    val_t i;
    val_t ans;

    ans = 0;

    for (i = 1;  i <= n;  ++i) {
        ans += SQR(i-1);
        ans += SQR(i);
        ans %= MOD;
    }

    return ans;
}

更新:我已经习惯于在这里看到我写错了公式的因子。现在纠正了。

答案 2 :(得分:1)

您的代码的迭代版本如下所示。你可以用它

    inline long long int formula(long long int n)
    {
        long long f = 1;
        for (int i = 2; i <= n; i++)
        {
            f = ((f % MOD + (1LL * (i - 1)*(i - 1)) % MOD) % MOD + (1LL * i*i) % MOD) % MOD;
        }
        return f;
    }

答案 3 :(得分:0)

如果您需要计算20亿的大小,那么循环将花费很长时间。然而,递归方程通常导致

sum [i * i+(i-1)*(i-1)] = sum [2* i * i - 2*i + 1]. 

您可以使用the sum of first n squares的等式和算术序列将其简化为:

2*n(n * n + 1) / 3

现在您可以使用* b%c =(a%c)*(b%c)进一步减少此项。但是,除以3和模数运算不通勤。所以你需要把等式写成

( ((2*(n % MOD)) %MOD) * (((n % MOD) * (n % MOD)) +1) %MOD) * 444009) % MOD

其中444009是3 mod MOD的模块化反转,即3 * 444009%MOD = 1。

编辑:添加了关于通勤模数和除法运算符的讨论,正如Raymond Chen指出的模数和除法不通勤。