牛客小白月赛24 J—建设道路

整理的算法模板:ACM算法模板总结(分类详细版)

链接:https://ac.nowcoder.com/acm/contest/5158/J
来源:牛客网
 

时间限制:C/C++ 1秒,其他语言2秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

牛牛国有 nnn 个城市,编号为 1−n1-n1−n,第 iii 个城市有一个价值 aia_iai​,牛国的国王牛阔落特别喜欢在牛牛国旅游,并且他不想每次旅游的时候都计算一遍走哪条路最短,于是他决定在任意两个城市之间建立一条双向道路,在第 iii 座城市和第 jjj 座城市之间建立双向道路的代价是 (ai−aj)2(a_i-a_j)^2(ai​−aj​)2,牛阔落希望你能算出这项工程的花费。由于答案太大,你只需要输出答案模 1e9+71e9+71e9+7 的余数

输入描述:

 

第一行一个整数 nnn,表示城市的数量。

第二行 nnn 以空格分隔的整数 a1,a2,...,ana1,a2,...,ana1,a2,...,an,表示第i座城市的价值。

输出描述:

输出一行一个数字,表示工程的花费模 1e9+71e9+71e9+7 的余数

示例1

输入

复制3 1 2 3

3
1 2 3

输出

复制6

6

说明

 

城市1到城市2的道路价值是(2 - 1)^ 2 = 1

城市2到城市3的道路价值是(3 - 2)^ 2 = 1

城市1到城市3的道路价值是(3 - 1)^ 2 = 4

总的花费 = 1 + 1 + 4 = 6

备注:

 

1≤n≤5e51\leq n\leq 5e51≤n≤5e5

1≤ai≤1e91\leq a_i\leq 1e91≤ai​≤1e9

建议使用 scanf 读入

 

补这道题的博客原因是貌似学到了一个新知识:

对于一个序列或者数组中的任意两个数做求和,然后求出来总和是多少;如果用二重循环,数据多一点就会超时;根据这道题发现一个规律;

\sum_{i=1}^{n}\sum_{j=i+1}^{n}(Ai+Aj)   =  (n-1)  *    \sum_{i=1}^{n}(Ai)

对于这道题,小哥哥们推的很详细;我就不阐述了;下面图面的题解是把 j 从 1 枚举到   i-1  这和 j 从 i+1 枚举到 n 的原理是一样的;(实在不行搞个简单的自己模拟一下就推出来了,eg:求1 2 3 4 5 的任意两个数和的总和)

需要注意的是一定要处处取模,数据太大,随时会爆int;

 牛客小白月赛24 J—建设道路_第1张图片

 

#include 
using namespace std;
typedef long long ll;
const int N=5e5,mod=1e9+7;
ll sum[N],a[N];
int main()
{
    int n;
    cin >>n;
    ll res=0,ans=0;
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
        res=(res+a[i]*a[i])%mod;
        sum[i]+=(a[i]+sum[i-1])%mod;
    }
    ans+=res%mod*(n-1)%mod;
    ll cnt=0;
    for(int i=1;i<=n;i++)
    {
        cnt+=2*a[i]*(sum[n]-sum[i])%mod;
    }
    printf("%lld\n",(ans-cnt+mod)%mod);
}

 

你可能感兴趣的:(基础算法——数论,算术)