AFO

牛客练习赛53

牛客练习赛53

定义一个无限长的数组,给定前n项,若i>n,则a[i]=a[i-n]。接下来有Q次询问,每次给定一个N,你只需回答

\[\sum_{l=1}^N{\sum_{r=l}^N \sum_{i=l}^{r} \sum_{j=l}^{r}{a[i]\times a[j]}}$$对1e9+7取模的结果。 化柿子略过 $$S_i=\sum_{j=1}^i a[j]\]

\[\sum_{i=1}^N S_i^2 - \sum_{i=1}^N \sum_{j=1}^N S_i\times S_j \]

后面那部分等差数列求和,前半部分用平方和公式

就这样吧


#include<iostream>
#include<cstring>
#include<algorithm>
#include<cstdio>
#define LL long long 
using namespace std;
const int P = 1e9+7;
const int M = 3100000;
int a[M],d[M],n,res,m,s,u[M],v[M];
LL g;

LL qick(int x,int y)
{
	int z=1;
	for(;y;y>>=1, x=(LL)x*x%P) if(y&1) z=(LL)z*x%P;
	return z;
}

int main()
{
	//freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++) scanf("%d",&a[i]), s=(s+a[i])%P;
	for(int i=1;i<=n;i++) d[i]=(d[i-1]+a[i])%P;
	for(int i=1;i<=n;i++) u[i]=(u[i-1]+d[i])%P;
	for(int i=1;i<=n;i++) v[i]=(v[i-1]+(LL)d[i]*d[i])%P;
	for(;m;m--)
	{
		scanf("%lld",&g); 
		LL w=g/n%P;
		LL S=((w-1ll)*w/2ll%P*d[n]%P*n%P+(LL)w*u[n]%P+u[g%n]+(LL)(g%n)*d[n]%P*w%P)%P;
		w-=1ll;
		LL O=(LL)w*(w+1ll)%P*(2ll*w+1ll)%P*qick(6,P-2)%P;
		//w+=1;
		LL S1=(LL)d[n]*d[n]%P*O%P*n%P;
		LL S2=(LL)w*(w+1ll)%P*d[n]%P*u[n]%P;
		LL S3=(LL)v[n]*(w+1ll)%P;
		w+=1ll;
		LL S4=(LL)w*s%P; LL S5=g%n;
		LL W=((LL)S5*S4%P*S4%P+2ll*S4%P*u[S5]%P+v[S5])%P;
		
		LL S6=(S1+S2+S3+W)%P*((g+1ll)%P)%P;
		S6=(S6-S*S%P+P)%P;
		printf("%lld\n",S6);
	}
}
posted @ 2019-10-12 15:53  ZUTTER☮  阅读(105)  评论(0编辑  收藏  举报