题解:P12518 「MSTOI-R1」Easy question

PART 1 思路

首先预处理 1 到 20 次幂的前缀和。
具体代码如下:

for(int k=1;k<=20;k++) 
	{
        p[k][0]=0;
        for(int i=1;i<=n;i++) 
		{
            int sum=1;
            sum=pow(a[i],k);
            p[k][i]=(p[k][i-1]+sum)%MOD;//k为几次方
        }
    }

其中用到了快速幂模板,可见P1226

然后分三点做题。

1.求l至r之间的值之和

由于数组已经过处理,可直接求和,输出其一次方形式即可,将 p[1][r] 与 p[1][l-1] 相减即为区间和。

int sum=(p[1][r]-p[1][l-1]+MOD)%MOD;
printf("%lld\n",sum);
2.求l至r之间的值的次方之和

和求和同理,只不过将一次方改为 k 次方。

int sum=(p[k][r]-p[k][l-1]+MOD)%MOD;
printf("%lld\n",sum);
3.重头戏!!!

前面两个只是开胃小菜,这才是重点!
但经过预处理,这部分的代码也是异常简短。

int v=(((p[2][r]-p[2][l-1]+MOD)%MOD)-((((((p[1][r]-p[1][l-1]+MOD)%MOD)*((p[1][r]-p[1][l-1]+MOD)%MOD))%MOD)*(pow((r-l+1),MOD-2)))%MOD)+MOD)%MOD;
printf("%lld\n",(v*(r-l+1))%MOD);

PART 2 Code

#include <bits/stdc++.h>
#define int long long
using namespace std;
const int MOD=998244353;
const int N=1e6+10;
int n,q,a[N],p[21][N];
int pow(int b,int a) 
{
    int res=1;
    b%=MOD;
    while(a>0) 
	{
        if(a&1) res=(res*b)%MOD;
        b=(b*b)%MOD;
        a>>=1;
    }
    return res;
}//快速幂模板
void init()
{
	for(int k=1;k<=20;k++) 
	{
        p[k][0]=0;
        for(int i=1;i<=n;i++) 
		{
            int sum=1;
            sum=pow(a[i],k);
            p[k][i]=(p[k][i-1]+sum)%MOD;
        }
    }
}//预处理
signed main() {
    scanf("%lld%lld",&n,&q);
    for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
    init();
    while(q--) 
	{
        int op,l,r;
        scanf("%lld%lld%lld",&op,&l,&r);
        if(op==1) 
		{
            int sum=(p[1][r]-p[1][l-1]+MOD)%MOD;
            printf("%lld\n",sum);
        } 
		else if(op==2) 
		{
            int k;
            scanf("%lld",&k);
            int sum=(p[k][r]-p[k][l-1]+MOD)%MOD;
            printf("%lld\n",sum);
        } 
		else if(op==3) 
		{
            int v=(((p[2][r]-p[2][l-1]+MOD)%MOD)-((((((p[1][r]-p[1][l-1]+MOD)%MOD)*((p[1][r]-p[1][l-1]+MOD)%MOD))%MOD)*(pow((r-l+1),MOD-2)))%MOD)+MOD)%MOD;
            printf("%lld\n",(v*(r-l+1))%MOD);
        }
    }
    return 0;
}

总而言之,这整篇题解的核心只有预处理,处理完后就非常简单了

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值