题解:AT_bcu30_f 数列と計算
posted on 2024-10-18 03:39:46 | under | source
来篇小清新的题解。
考虑让每个极大连续乘积段(即全用 * 连接的)的贡献挂在它最后一个元素上,记 \(f_i\) 表示以 \(i\) 为结尾的乘积段在所有情况下的价值之和,那么答案就是 \(\sum 2^{\max(0,n-i-1)}f_i\)。
\(f\) 的转移是容易的:\(f_i\gets a_if_{i-1}+a_i2^{\max(0,i-2)}\)。即分讨 \(a_i\) 前面是 * 还是 +。
复杂度 \(O(n)\)。
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N = 1e5 + 5, mod = 1e9 + 7;
int n, a, f[N], pw[N], ans;
signed main(){
pw[0] = 1;
for(int i = 1; i < N; ++i) pw[i] = pw[i - 1] * 2ll % mod;
cin >> n;
for(int i = 1; i <= n; ++i){
scanf("%lld", &a);
f[i] = (f[i - 1] * a % mod + pw[max(0ll, i - 2)] * a % mod) % mod;
ans = (ans + f[i] * pw[max(0ll, n - i - 1)] % mod) % mod;
}
cout << ans;
return 0;
}

浙公网安备 33010602011771号