P14967 『LHB-OI』Round 1 B题 Watching the Moon
题意
题目内容
给定长度为 \(n\),的序列 \(a\)。
求
\[\sum_{k=1}^{n}
\left\{
a_k
+
\sum_{i=1}^{k-1}\sum_{j=1}^{k-1}
\Biggl[
\Biggl(
\prod_{l=1}^{i}
a_{l}^{\,2^{\,i-l}}
\Biggr)
\Biggl(
\prod_{l=1}^{j}
a_{l}^{\,2^{\,j-l}}
\Biggr)
\Biggr]
\right\}
\]
对 \(10^9+7\) 取模后的结果。
数据范围与提示
\(n\le 5\times 10^6\),\(a_i\le 10^9\)。
时间限制 \(300ms\), 空间限制 \(5MB\)
解决
尝试缩减式子,
优化其中的 :
\[\Biggl(
\prod_{l=1}^{i}
a_{l}^{\,2^{\,i-l}}
\Biggr) 和 \Biggl(
\prod_{l=1}^{j}
a_{l}^{\,2^{\,j-l}}
\Biggr)\]
尝试第推处理。
首先我们定义:
\[f(x)=\prod_{l=1}^{x}a_l^{2^{x-l}}
\]
我们尝试预处理每个 \(f(i)\)。
\[f(x+1)=\prod_{l=1}^{x}a_l^{2^{x-l+1}} * a_{x+1}=\prod_{l=1}^{x}a_l^{2^{x-l}*2} * a_{x+1}=f(x)^2 * a_{x+1}
\]
得结论:
\[f(x+1)=f(x)^2*a_{x+1}
\]
\[f(x)=f(x-1)^2*a_x
\]
接下来我们要求:
\[\sum_{k=1}^{n}
\left\{
a_k
+
\sum_{i=1}^{k-1}\sum_{j=1}^{k-1}
\Biggl[
\Biggl(
\prod_{l=1}^{i}
a_{l}^{\,2^{\,i-l}}
\Biggr)
\Biggl(
\prod_{l=1}^{j}
a_{l}^{\,2^{\,j-l}}
\Biggr)
\Biggr]
\right\}
\]
推导:
\[\sum_{k=1}^{n}
\left\{
a_k
+
\sum_{i=1}^{k-1}\sum_{j=1}^{k-1}
\Biggl[
\Biggl(
\prod_{l=1}^{i}
a_{l}^{\,2^{\,i-l}}
\Biggr)
\Biggl(
\prod_{l=1}^{j}
a_{l}^{\,2^{\,j-l}}
\Biggr)
\Biggr]
\right\}
\]
\[=\sum_{k=1}^{n}
\left\{
a_k
+
\sum_{i=1}^{k-1}\sum_{j=1}^{k-1}
\Biggl[
f(i)
f(j)
\Biggr]
\right\}
\]
\[=\sum_{k=1}^{n}
\left\{
a_k
+
\Biggr[ \sum_{i=1}^{k-1}f(i)*\sum_{j=1}^{k-1}f(j)\Biggr]
\right\}
\]
\[=\sum_{k=1}^{n}
\left\{
a_k
+
\Biggr( \sum_{i=1}^{k-1}f(i)\Biggr)^2
\right\}
\]
\[=\sum_{k=1}^{n}
a_k
+
\sum_{k=1}^{n}\Biggr[\Biggr( \sum_{i=1}^{k-1}f(i)\Biggr)^2\Biggr]
\]
得
\[\sum_{k=1}^{n}
\left\{
a_k
+
\sum_{i=1}^{k-1}\sum_{j=1}^{k-1}
\Biggl[
\Biggl(
\prod_{l=1}^{i}
a_{l}^{\,2^{\,i-l}}
\Biggr)
\Biggl(
\prod_{l=1}^{j}
a_{l}^{\,2^{\,j-l}}
\Biggr)
\Biggr]
\right\}=\sum_{k=1}^{n}
a_k
+
\sum_{k=1}^{n}\Biggr[\Biggr( \sum_{i=1}^{k-1}f(i)\Biggr)^2\Biggr]
\]
根据化后的公式编码。
分别建立变量用于第推函数 \(f\),记录\(f\)的和,及答案求和变量。
本题时限较短。注意常数优化。
#include <bits/stdc++.h>
typedef unsigned long long ll;
const ll mod=1e9+7;
using std::cin;
using std::cout;
template< typename Type >
inline Type fread(Type* p) {
Type ret = 0, sgn = 0, ch = getchar();
while (!isdigit(ch)) {
sgn |= ch == '-', ch = getchar();
}
while (isdigit(ch)) ret = ret * 10 + ch - '0', ch = getchar();
if (p != nullptr) {
*p = Type(sgn ? -ret : ret);
}
return sgn ? -ret : ret;
}
ll n,sum=0,f=1,temp,ans=0;
int main() {
//freopen("input","r",stdin);
//cin>>n;
//scanf("%llu",&n);
fread(&n);
for(ll i=1;i<=n;++i) {
ll val=0;
// scanf("%llu",&val);
fread(&val);
f=f%mod*f%mod*val%mod;
f%=mod;
ans+=temp%mod*temp%mod;
ans%=mod;
ans+=val;
ans%=mod;
temp+=f;
temp%=mod;
}
printf("%llu\n",ans);
return 0;
}

浙公网安备 33010602011771号