该系列的第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;
}
答案 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。