XJTUOJ #1048 nocriz送温暖

题目描述

nocriz是个友善的出题人。

\(n\)个数\(a_1,a_2,...,a_n\),有\(q\)次询问,每次问\(a_l\times a_l+1\times ...\times a_r\) \(mod\) \(998244353\) 的值。

输入格式

第一行一行两个整数\(n,q\)

第二行一行\(n\)个整数\(a_1,a_2,...,a_n\)

接下来\(q\)行,每行两个整数\(l_i,r_i\)

输出格式

输出\(q\)行,每行一个整数,代表答案。

数据范围

\(1\leq n,q \leq 2*10^5\)
\(1\leq a_i \leq 998244352\)

思路

很显然这是一道大水题,解决的办法也有很多,比如说用线段树等数据结构,这里就不细说了。更简单的方法是利用前缀和思想。\(Ans(l,r)=pre[r]/pre[l-1]\)

众所周知,带模数时不能直接除,要用乘法逆元,我这里使用的是扩展欧几里得算法。

代码

#include<cstdio>
#include<cstdlib>
#include<algorithm>
#define mod 998244353
#define ll long long
#define maxn (int)(2*1e5+10)
ll a[maxn],X,Y;
using namespace std;
void exgcd(ll m,ll n){
	if(!n){
		X=1,Y=0;
		return;
	}
	exgcd(n,m%n);
	ll t=X;
	X=Y;
	Y=t-m/n*Y;
	return;
}
ll inv(ll t){
	exgcd(mod,t);
	return (Y+mod)%mod;
}
int main(){
	int n,i,l,r,q;
	ll x,ans;
	a[0]=1;
	scanf("%d%d",&n,&q);
	for(i=1;i<=n;i++){
		scanf("%lld",&x);
		a[i]=a[i-1]*x%mod;
	}
	for(i=1;i<=q;i++){
		scanf("%d%d",&l,&r);
		ans=a[r]*inv(a[l-1])%mod;
		printf("%lld\n",ans);
	}
	return 0;
} 
posted @ 2020-10-10 12:00  文艺平衡树  阅读(87)  评论(0编辑  收藏  举报