【问题标题】:How to calculate sum of the given series如何计算给定系列的总和
【发布时间】:2014-10-26 09:33:31
【问题描述】:

数列的第 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) 模 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;
}

【问题讨论】:

  • 如果您更改包含和命名空间,这是 C,而不是 C++。这样的组合会在这里得到反对,你应该改变它。如果你已经有一个简单的方程,为什么不使用它呢?而不是那么多模数的东西......
  • 我看不到你程序中所有部分的总和......但是你在那里做什么?两个scanf'ed变量是第一个奇怪的事情。 (现在编辑无济于事,因为显然你不知道自己在做什么)
  • n 的值最大为 10^9 会导致溢出。
  • 不,不会。你为什么这么认为?
  • n 立方体将是 10^27,对于 n=10^9。并且在 64 位中它不会变得合适。

标签: c overflow modulo polynomial-math


【解决方案1】:

您的代码中有多个问题。

问题 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 将is 视为unsigned long long

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

问题 3
P(n) 纯数学且没有模对每个自然数 n>=1 都是正数。
但是 P(0) 是负的,而且更重要的是:方程的四个部分 modul´t
并且加/减在一起可能会导致负数,这是全等的
到积极的预期结果,但 C 不知道。
所以,使用signed而不是unsigned,并且在整个计算之后,检查
如果结果是 &lt;0 并添加 c 使其成为 &gt;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。

【讨论】:

    猜你喜欢
    • 2018-08-07
    • 2019-03-13
    • 1970-01-01
    • 1970-01-01
    • 2017-04-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-20
    相关资源
    最近更新 更多