来源:牛客网
@[toc]
时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 131072K,其他语言262144K 64bit IO Format: %lld
题目描述
定义S(n) = 12 + 22 + … + n2,输出S(n) % 1000000007。
注意:1 < n < 1e18。
输入描述:
多组输入,输入直到遇到EOF为止;
第一行输入一个正整数n。
输出描述:
输出S(n) % 1000000007的结果。
示例1
输入
1 2 1000
输出
1 5 333833500
题解:
平方和公式:1^2^+2^2^+3^2^+......+n^2^=n(n+1)(2n+1)/6
(建议补一补高中的一些公式,我也没想起来 )
注意题目是要mod的
模运算:
(a + b) % p = (a % p + b % p) % p
(a - b) % p = (a % p - b % p) % p
(a * b) % p = (a % p * b % p) % p
a ^b^ % p = ((a % p)^b^) % p
我们可以发现唯独没有除法的模运算,但是公式中有个 /6 需要处理,那我们可以用逆元的方式将除法变成乘法
逆元:整数a,b,满足a * b = 1(mod m),那么称b是a的模m乘法逆元
比如:A/B%C我们可以写成A * (1 / B)% C,这样就是AX%C的形式,如何求X?和上面的逆元结合起来就OK了
这样/6%mod,我就可以写成 inv(6)%mod
求逆元的方法这里就不详细介绍了
代码:
#include<iostream> #include<cstdio> using namespace std; typedef long long ll; const ll mod=1000000007; ll exgcd(ll a,ll b,ll &x,ll &y)//扩展欧几里得算法 { if(b==0) { x=1; y=0; return a; //到达递归边界开始向上一层返回 } ll gcd=exgcd(b,a%b,x,y); ll y1=y; //把x y变成上一层的 ll x1=x; y=x1-(a/b)*y1; x=y1; return gcd; //得到a b的最大公因数 } ll inv(ll a,ll mod){ ll x,y; ll gcd=exgcd(a,mod,x,y); if(gcd!=1)return -1; else return (x+mod)%mod; } int main() { ll n; while(cin>>n){ ll ans=0; ans=(((n%mod)*((n+1)%mod)%mod*((2*n+1)%mod))%mod); ll inv6=inv(6,mod); ans=(ans%mod*inv6%mod)%mod; cout<<ans<<endl; } return 0; }