zoukankan      html  css  js  c++  java
  • 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})展开如下:

    [ egin{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))

    [ egin{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)相同的项合(可以相互消去)并描绘得到下面的东西,为了方便,我还是用矩阵表示

    [ egin{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;
    }
    
  • 相关阅读:
    归并、希尔排序
    堆排序
    [模板] 最小树形图/朱刘算法
    [模板] 常系数线性递推
    [模板] Kruskal算法 && 克鲁斯卡尔重构树
    [模板] 斯特林数,性质以及求法
    这几天想干什么
    奇怪的 Markdown / LaTeX 笔记
    [模板] 各种莫队
    [模板] 2-SAT 问题
  • 原文地址:https://www.cnblogs.com/FlyerBird/p/9457786.html
Copyright © 2011-2022 走看看