P12518「MSTOI-R1」Easy question 题解
由于我们在操作时需要用到区间和以及区间次方和,而 \(k\) 最大只有 \(20\),所以完全可以直接开一个数组维护次方和。定义 \(s_{i,j}\) 表示 \(\sum\limits_{k=1}^{i}a^j\)。
对于操作 1,直接输出预处理的一次方区间和 \(s_{r,1}-s_{l-1,1}\)。
对于操作 2,直接输出预处理的 \(k\) 次方和 \(s_{r,k}-s_{l-1,k}\)。
对于操作 3,我们考虑将式子拆开。
\[\begin{aligned}
{}&(r-l+1) \sum_{i=l}^r\left(a_i-\overline a\right)^2&\\
=&(r-l+1)\sum_{i=l}^{r}{a_i}^2+\overline a^2-2a_i\overline a&\\
=&(r-l+1)[(\sum_{i=l}^r{a_i}^2)+(r-l+1)\overline a^2-2\overline a(\sum_{i=l}^ra_i)]&\\
=&(r-l+1)[(\sum_{i=l}^r{a_i}^2)+(\sum_{i=l}^ra_i)\overline a-2\overline a(\sum_{i=l}^ra_i)]&\\
=&(r-l+1)[(\sum_{i=l}^r{a_i}^2)-\overline a(\sum_{i=l}^ra_i)]&\\
=&(r-l+1)(\sum_{i=l}^r{a_i}^2)-(r-l+1)\overline a(\sum_{i=l}^ra_i)&\\
=&(r-l+1)(\sum_{i=l}^r{a_i}^2)-(\sum_{i=l}^ra_i)^2
\end{aligned}
\]
再使用预处理的 \(s\) 数组,可以得到 \(ans=(r-l+1)(s_{r,2}-s_{l-1,2})-(s_{r,1}-s_{l-1,1})^2\)。
#include<iostream>
#include<cstdio>
using namespace std;
typedef long long ll;
const int N=1e6+100,K=25;
const ll MOD=998244353;
int n,q,op;
ll a[N],s[N][K],u,v,w,ans;
int main()
{
//freopen("data1.in","r",stdin);
scanf("%d%d",&n,&q);
for(int i=1;i<=n;i++)
{
scanf("%lld",&a[i]);
s[i][0]=1;
for(int j=1;j<=20;j++) s[i][j]=s[i][j-1]*a[i]%MOD;
for(int j=1;j<=20;j++)
{
s[i][j]=(s[i][j]+s[i-1][j])%MOD;
//printf("%d %d %lld\n",i,j,s[i][j]);
}
}
while(q--)
{
scanf("%d%lld%lld",&op,&u,&v);
if(op==1) ans=(s[v][1]+MOD-s[u-1][1])%MOD;
else if(op==2)
{
scanf("%d",&w);
ans=(s[v][w]+MOD-s[u-1][w])%MOD;
}
else ans=((v-u+1)*(s[v][2]+MOD-s[u-1][2])%MOD+MOD-(s[v][1]+MOD-s[u-1][1])%MOD*(s[v][1]+MOD-s[u-1][1])%MOD)%MOD;
printf("%lld\n",ans);
}
return 0;
}

浙公网安备 33010602011771号