2018 Wannafly summer camp Day8--区间权值

区间权值
小Bo有\(n\)个正整数\(a_1\)……\(a_n\),以及一个权值序列\(w_1\)……\(w_n\),现在她定义\(f(l,r)=(\sum_{i=l}^r a_i^2) *w_{r-l+1}\)
现在他想知道\(\sum_{l=1}^n \sum_{r=l}^n f(l,r)\)的值,需要你来帮帮他,你只需要输出答案对\(10^9+7\)取模后的值。
输入格式
第一行一个正整数\(n\)
第二行\(n\)个整数\(a_1\)……\(a_n\)
第三行\(n\)个整数\(a_1\)……\(a_n\)
输出格式
输出答案\(10^9+7\)取模
样例输入
3
1 1 1
1 1 1
样例输出
10
数据范围
\(1<=n<=3*10^5\)
\(1<=a_i<=10^7\)
\(1<=w_i<=10^7\)

思路:
\(f(l,r)=(\sum_{i=l}^r a_i^2) *w_{r-l+1}\)展开如下:

\[ \begin{pmatrix} a_1w_1 & ……\\ (a_1+a_2)w_2 & a_2w_1 & …… \\ (a_1+a_2+a_3)w_3 & (a_2+a_3)w_2 & a_3w_1 & ……\\ (a_1+a_2+a_3+a_4)w_4 & (a_2+a_3+a_4)w_3 & (a_3+a_4)w_2 \\ …… & …… & ……\\ (a_1+a_2+……+a_n)w_n & (a_2+……+a_n)w_{n-1} & …… & a_nw_1 \\ \end{pmatrix} \]

从第一列可以想到前缀和,所以先求出前缀和\(f[i](0<=i<=n)\)

\[ \begin{pmatrix} (f_1-f_0)w_1 & ……\\ (f_2-f_0)w_2 & (f_2-f_1)w_1 & …… \\ (f_3-f_0)w_3 & (f_3-f_1)w_2 & (f_3-f_2)w_1 & ……\\ (f_4-f_0)w_4 & (f_4-f_1)w_3 & (f_4-f_2)w_2 \\ …… & …… & ……\\ (f_n-f_0)w_n & (f_n-f_1)w_{n-1} & …… & (f_n-f_{n-1})w_1 \\ \end{pmatrix} \]

然后将\(w_i\)相同的项合(可以相互消去)并描绘得到下面的东西,为了方便,我还是用矩阵表示

\[ \begin{pmatrix} (f_n)w_1 \\ (f_n+f_{n-1}-f_1)w_3\\ (f_n+f_{n-1}+f_{n-2}-f_1-f_2)w_3\\ (f_n+f_{n-1}+f_{n-2}+f_{n-3}-f_1-f_2-f_3)w_4\\ ………… \\ (f_n+f_n-1+……-f_1-f_2-……f_{n-1})w_n \end{pmatrix} \]

现在敲是会TLE的,复杂度太高
所以再考虑一次\(f_i\)的前缀和\(g_i\),
上面就可以将\(f_i\)转换成\(g[n]-g[n-i]-g[i-1]\)
还有一个问题,由于有减法,所以可能答案出现负数,所以最后需要加模再取模。

#include <cstdio>
#include <cstring>
#include <cmath>
#include<algorithm>
#include<iostream>
using namespace std;
typedef long long ll;
const ll mo=1e9+7;
const int maxn=3e5+5;
ll a[maxn],w[maxn],f[maxn],g[maxn],ans=0;
int main()
{
	int n;
	scanf("%d",&n);
	g[0]=f[0]=0;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        f[i]=a[i]+f[i-1];
        g[i]=(f[i]+g[i-1])%mo;
    }
    for(int i=1;i<=n;i++)
        cin>>w[i];
    for(int i=1;i<=n;i++){
        ans=(ans+(g[n]-g[n-i]-g[i-1])*w[i]%mo)%mo;
    }
    cout<<(ans+mo)%mo<<endl;
    return 0;
}
posted @ 2018-08-10 22:17  Chasssser  阅读(320)  评论(0编辑  收藏  举报