• P5686 和积和


    写在前面

    数学题接触的少,卡了半下午,愣是没想到直接往前缀和上考虑,按元素强推莽了半下午

    Description

    直接跳转到题目去啊

    Solution

    \(A,B\) 的前缀和序列分别为 \(sA,sB\)

    那么随便找一组数据,就会发现答案可以由一坨下标相等的前缀和积和减去另外一坨下标不等的前缀和积和。

    而且下标相等的部分正好是对于每个下标 \(i\)\(sA_i sB_i\) 都被计算了 \(n\) 次。

    那么加的部分就很好处理了。即:

    \[n \bullet \sum_{i=1}^{n}sA_i sB_i \]

    减的部分不难看出是 \(sA\)\(sB\) 所有的一一对应且下标不同的组合。

    所以对于每个 \(sA_i\),只需要让它去乘以所有的下标 \(j<i\)\(sB_j\),并将结果求和。

    对于每个 \(sb_i\) 亦然。

    提公因式之后,由于计算过程是静态的,这个过程显然可以通过再预处理出一个超级前缀和 \(SA,Sb\),即前缀和的前缀和来优化实现。

    那么这部分的计算式即为:

    \[\sum_{i=2}^{n}sA_i SB_{i-1} + sB_i SA_{i-1} \]

    总的式子即为:

    \[n \cdot \sum_{i=1}^{n}sA_i sB_i - \sum_{i=2}^{n}sA_i SB_{i-1} + sB_i SA_{i-1} \]

    根据计算式易知时间复杂度为 \(\Theta(n)\)

    code:

    #include<bits/stdc++.h>
    
    #define LL long long
    
    using namespace std;
    const int Maxn = 5e5 + 5;
    const int mod = 1e9 + 7;
    
    inline LL read() {
      LL f = 1, w = 0; char ch = getchar();
      for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
      for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
      return f * w;
    }
    
    LL n, t;
    LL a[Maxn], b[Maxn];
    LL Sa[Maxn], Sb[Maxn];
    LL sa[Maxn], sb[Maxn];
    LL ans;
    
    int main()
    {
    	n = read();
    	t = (n % mod + 1 % mod) % mod;
    	for(register int i = 1; i <= n; ++i) a[i] = read() % mod;
    	for(register int i = 1; i <= n; ++i) b[i] = read() % mod;
    	for(register int i = 1; i <= n; ++i)
    	{
    		sa[i] = ((sa[i - 1] % mod) + (a[i] % mod)) % mod;
    		sb[i] = ((sb[i - 1] % mod) + (b[i] % mod)) % mod;
    		Sa[i] = ((Sa[i - 1] % mod) + (sa[i] % mod)) % mod;
    		Sb[i] = ((Sb[i - 1] % mod) + (sb[i] % mod)) % mod;
    		ans = ((ans % mod) + (((((sa[i] % mod) * (sb[i] % mod)) % mod) * (n % mod)) % mod)) % mod;
    	}
    	for(register int i = 2; i <= n; ++i)
    	{
    		ans = ((ans % mod) - (((sa[i] % mod) * (Sb[i - 1] % mod)) % mod) + mod) % mod;
    		ans = ((ans % mod) - (((sb[i] % mod) * (Sa[i - 1] % mod)) % mod) + mod) % mod;
    	}
    	printf("%lld", ans);
    	return 0;
    }
    
  • 相关阅读:
    SSP状态寄存器SSPSTAT
    【PIC学习第18例】PIC16F877A 内部EEPROM读写实验
    批量去除flv专辑的片头
    .Net并行库介绍——Task(1)
    一个下载游戏封面的站点
    一个猜数字的小游戏
    RamDisk加速Windows 7?
    .Net并行库介绍——Task(2)
    数独的自动出题算法
    Live Messenger 2009登陆错误的解决方法
  • 原文地址:https://www.cnblogs.com/zimujun/p/13622543.html
Copyright © 2020-2023  润新知