1. 程式人生 > >牛客國慶集訓派對Day4——G 區間權值(找規律,雙重字首和)

牛客國慶集訓派對Day4——G 區間權值(找規律,雙重字首和)

題目大意:       小 Bo 有 n 個正整數 a1..an,以及一個權值序列 w1…wn,現在他定義       現在他想知道 的值,需要你來幫幫他。你只需要輸出答案對 109+7 取模後的值

題解:

題目要求的是

 f(1,1)+f(1,2)+f(1,3)+...+f(1,n)

f(2,2)+f(2,3)+...+f(2,n)

f(3,3)+f(3,4)+...+f(3.n)

f(4,4)+f(4,5)...

...

f(n,n)

sum[1]w1\ + \ sum[2]w2\ +\ sum[3]w3+...\ +\ sum[n]wn

(sum[2]-sum[1])w1+(sum[3]-sum[1])w2+...+(sum[n]-sum[1])w_{n-1}

(sum[3]-sum[2])w1+(sum[4]-sum[2])w2+...+(sum[n]-sum[2])w_{n-1}

可以發現每一行的對應列的w因數相同,對應相加可得

w1(sum[n])

w2(sum[n]-sum[n-1]-sum[1])

w3(sum[n]-sm[n-1]-sum[n-2]-sum[2]-sum[1])

但是這樣求的話也是需要兩重迴圈來求......於是再來一次字首和(S[n]為sum的字首)

即  wi(S_{n}-S_{n-i}-S_{i-1})

#include <cstdio>
#include <cstring>
#include <cmath>
#include<algorithm>
#include<iostream>
#define mod 1000000007
using namespace std;
typedef long long ll;
ll sum[300010];
ll S[300010];
int a[300010],w[300010];
int main()
{
    //freopen("input.txt","r",stdin);
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;++i)
    {
        scanf("%d",&a[i]);
        sum[i]=sum[i-1]+a[i];
    }
    for(int i=1;i<=n;++i)
        scanf("%d",&w[i]);
    for(int i=1;i<=n;++i)
        S[i]=S[i-1]+sum[i],S[i]%=mod;
    ll ans=0;
    for(int i=1;i<=n;++i)
    {
        ans+=((S[n]-S[n-i]-S[i-1]+mod)%mod*w[i]%mod)%mod;
        ans%=mod;
    }
    printf("%lld\n",ans);
    return 0;
}