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;
}
posted @ 2025-06-14 14:29  MinimumSpanningTree  阅读(1)  评论(0)    收藏  举报