图片说明

相信大家都理解了题目得意思,就是求一段子段得乘积并取模得最大余数
思路:尺取法,l代表左端点,r代表右端点。l先不动,r往前扫描,如果成功扫到,有k个非0元素的子段就累成起来,最后把最左端的元素除了,左端点往前移动,l++再继续扫描。再未达到k个非零元素的子段前,如果遇到0,当前的区间就废了 ,左端点直接到0的下一个位置。继续扫描。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const ll mod = 998244353;
const ll N  = 200005;
ll a[N];
ll Max = 0;//记录最终结果 
ll sum = 1;
ll Qpow(ll x,ll k)//快速幂求逆元 
{
    ll ans = 1;
    while(k)
    {
        if(k%2!=0) ans = ans*x%mod;
        k=k>>1;
        x=x*x%mod;
    }
    return ans;
}
int main()
{
    ll n,k;
    cin>>n>>k; 
    for(int i=1;i<=n;i++)
    {
       cin>>a[i];    
    }
    ll l = 1; //尺取法 
    ll r = 1;
    while(r<=n)
    {
        if(a[r]) //不是0就累乘直到达到k段子段 
        {
            sum=(sum*a[r])%mod;//sum是每一次扫描成功的值 
            if((r-l+1)%k==0) //达到k子段 
            {
                if(sum>Max) Max = sum;//题上要求取最大的 
                sum = sum*Qpow(a[l],mod-2)%mod;//逆元 ,原本是sum=sum/a[l] 。
                //一次扫描成功后,就吧最左端的元素除掉,再继续扫描。当然不能直接除 ,
                //这里需要用到逆元知识,不懂的可以去了解下 ,反正我那个式子就=(a[l]*a[l+1]*..*a[r])/a[l] 
                //我是这样理解的,因为才学,可能有错误的地方,请指出 
                l++;
            }

        }
        else  //再未达到k个非零元素的子段前,如果遇到0,当前的区间就废了  
        {
             l = r + 1;// 左端点直接到0的下一个位置 
             sum = 1;//sum归1 
        }
        r++;
    }
    cout<<Max<<endl;
    return 0;
}

如果还有不明白的,欢迎提问。其实,虽然我写的代码,但是,我有一点不明白(太菜了),为何,求逆元那里,sum = sum*Qpow(a[l],mod-2)%mod;这里还要取模,这个是我碰对的,没取模就不能过,希望大佬指教。