Problem
题意:给定n(<=2e5)的序列和k,求长度为 k 的连续子段的乘积对 998244353 取模余数的最大值
Solutions
1.线段树
思路:线段树维护区间乘积,枚举起点查询[i,i+k-1]的乘积更新最大值
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
#include<queue>
#include<math.h>
#include<set>
#include<vector>
using namespace std;
#define Inf 0x7fffffff
typedef long long ll;
const int N=200007;
const ll p=998244353;
int n,o;
ll a[N],t[N*4],ans;
inline void push_up(int k){
t[k]=(t[k<<1]*t[k<<1|1])%p;
}
void build(int l,int r,int k){
if(l==r){
t[k]=a[l];
return;
}
int mid=(l+r)>>1;
build(l,mid,k<<1);
build(mid+1,r,k<<1|1);
push_up(k);
}
ll query(int L,int R,int l,int r,int k){
if(L<=l&&R>=r)return t[k];
int mid=(l+r)>>1;
ll re=1;
if(L<=mid)re=(re*query(L,R,l,mid,k<<1))%p;
if(R>mid)re=(re*query(L,R,mid+1,r,k<<1|1))%p;
return re;
}
int main(){
cin>>n>>o;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
build(1,n,1);
for(int i=1;i<=n-o+1;i++){
ll now=query(i,i+o-1,1,n,1);
ans=max(ans,now);
}
cout<<ans;
}
2.乘法逆元
思路:尺取法+乘法逆元。因为模数p为质数,由费马小定理, ai*aip-2≡1 (mod p),所以ai于aip-2互为乘法逆元,这样就可以处理尺取法里的除法了。(注意处理ai为0的情况)
乘法逆元:a/b mod p = a*B mod p, 其中B是b关于模p的乘法逆元
#include<iostream>
#include<stdio.h>
#include<string.h>
#include<map>
#include<algorithm>
#include<queue>
#include<math.h>
#include<set>
#include<vector>
using namespace std;
#define Inf 0x7fffffff
typedef long long ll;
const int N=200007;
const ll p=998244353;
int n,k;
ll a[N],ans;
ll qpow(ll x,ll e,ll mod){
ll re=1;
while(e){
if(e&1){
re=re*x%mod;
}
x=x*x%mod;
e>>=1;
}
return re%mod;
}
int main(){
cin>>n>>k;
for(int i=1;i<=n;i++)scanf("%lld",&a[i]);
int l=1,r=0;
ll now=1;
while(++r<=n){
while(r-l+1>k)now=(now*qpow(a[l++],p-2,p))%p;
if(a[r]==0){
now=1;
l=r+1;
}else{
now=(now*a[r])%p;
if(r-l+1==k)ans=max(ans,now);
}
}
cout<<ans;
}