序列求和

    技术2024-06-03  74

    来源:牛客网

    文章目录

    题目描述题解:代码:

    时间限制: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

    题解:

    平方和公式:12+22+32+…+n2=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; }
    Processed: 0.020, SQL: 9