题目
样例输出
解析
其实就是一个循环乘,给你n个数,要求两两相乘的和,任何两个数都要相乘且只乘一次。
暴力
就是循环,两层,会是n^2
for(int i=0;i<n;i++){
for(int j=i+1;j<n;j++){
ans=ans+a[i]*a[j]%N;
}
}
因为给的n的数据是2*105,所以n2的复杂度肯定超时
先求和再相乘
相当于
a1*(a2+a3+a4……+an)+a2*(a3+a4+a5……+an)+a3*(a4+a5+a6+……+an)…
我们可以求一下前缀和,再相乘。
#include<bits/stdc++.h>
#include<cstring>
using namespace std;
#define ll long long
#define N 1000000007
ll arr[2*1000001];
ll qq[2*1000001];//qq存的就是前缀和
int main(){
ll a,b,c;
ll n;
ll ans=0;
cin>>n;
for(ll i=1;i<=n;i++){
scanf("%lld",&arr[i]);
qq[i]=(qq[i-1]+arr[i])%N; //求前缀和
}
for(ll i=1;i<n;i++){
ans=(ans+(arr[i]*(qq[n]-qq[i]+N)%N))%N;//相乘
}
cout<<ans<<endl;
return 0;
}
但是需要注意的是
ans=(ans+(arr[i]*(qq[n]-qq[i]+N)%N))%N;//相乘
上个代码中有个qq[n]-qq[i] ,因为qq数组在求和的时候都已经取余过了,所以说可能相减小于0,举个例子,22>13.但如果我对这两个数都对10取余,就变成2<3了,所以要再加上一个N(所要取余的数)
当时因为这个地方没注意一直报错