如何计算给定系列的总和

时间:2014-10-26 09:33:32

标签: c overflow modulo polynomial-math

该系列的第n个术语是f(n)。

      f(n) = 1, when n=1
      f(n)= ((n-1)*(8*(n–2)* 2+ 20)+4) , when n>1
      P(n)=f(1)+f(2)+.....f(n)
      1<=n<=10^9

对于给定的n,我们必须找到P(n)modulo 10 ^ 9 + 7。

我解决了这个等式,最后得到了答案           P(N)=(16N ^ 3-18n ^ 2 + 14N-12)/ 3

当我用c ++实现它时会出现问题。

如下所示代码告诉我它有什么问题以及如何解决它?

#include<stdio.h>

#define c 1000000007

int main()
{
long long int t,n,sum;
scanf("%lld",&t);
while(t--)
{
    sum=0;
    scanf("%lld",&n);
    if(n==1)
        printf("1\n");
    else
    {
        sum=(((16*(((((n%c)*(n%c))%c)*(n%c))%c)%c)+14*(n%c))%c-(18*(((n%c)*(n%c))%c)%c+12)%c)/3;
        sum++;
        printf("%lld\n",sum);
    }
}
return 0;
}

1 个答案:

答案 0 :(得分:0)

您的代码中存在多个问题。

问题1
long long b = ((a%c)*(a%c))%c;这样的表达式,a和b为long long
和c只是一个“普通数字”,即。 int,仍然受到int溢出,没有
使用long long的全部功能。原因是模数的结果:

long long = ((long long % int) * (long long % int)) % int;
long long = (int * int) % int;
long long = int % int; //overflow here
long long = int;
long long = long long; //expanding too late
//finished

作为检查(http://ideone.com/kIyM7K)的示例:

#include <iostream>
using namespace std;

int main() {
    int i = 1000000;
    long long ll = 1000000;
    cout<< ((999999%i)*(999999%i)*(999999%i)) << endl;
    cout<< ((999999%ll)*(999999%ll)*(999999%ll)) << endl;
    return 0;
}

在您的代码中,1000000007不是long long ...
使用1000000007ULL视为unsigned long long

问题2
您在printf和scanf中使用(或至少“使用”,在编辑之前)%lld 对于unsigned long long%llu%lld将是签名的long long

问题3
对于每个自然数n> = 1,纯粹数学且没有模数的P(n)是正的 但是P(0)是负的,更重要的是:你方程的四个部分是模数 并且一起加/减可能导致负数,这是一致的 对于积极的预期结果,但C不知道。
因此,请使用signed代替unsigned,并在整个计算后检查
如果结果为<0并向其添加c以使其>0

问题4
在长公式中某处括号和运算符优先级的问题 一个工作示例,但没有循环和输入:

#include<stdio.h>
int main()
{
    signed long long n, res, c;
    n = 2456ULL;
    c = 1000000007ULL;
    signed long long part1 = (16*(((n%c)*(n%c)%c)*(n%c)%c))%c;
    signed long long part2 = (18*((n%c)*(n%c)%c))%c;
    signed long long part3 = (14*(n%c))%c;
    res = ((part1 - part2 + part3 - 12)%c)/3 + 1;
    printf("%lld\n", res);
    return 0;
}

不是问题
你不需要特别检查n = 1,因为 无论如何,整个计算将导致1。