刚开始以为就是一个前缀和加双指针,遍历一下就好了
刚开始的思路就搞一个S数组然后把输入进去的数组前i位相乘的到S[i]数组,然后当i>=k了的时候S[i]/a[i-k],然后代码写完提交发现我没有考虑0的情况。
然后等题解出来发现原来还有逆元这种骚东西。不愧是我,小菜鸡。还是太菜了啥都不知道。
具体看大佬的代码吧,都标注好了的。
当然此处大佬用的是快速幂求逆元。
#include <iostream> #include <cstdio> #include <stack> #include <string> using namespace std; typedef long long ll; const int maxn=200010; const ll mod=998244353; ll a[maxn]; //如上求逆元 ll poww(ll a,ll n) { ll res=1; while(n>0) { if(n&1) res=(res*a)%mod; a=(a*a)%mod; n>>=1; } return res; } // 就是求a^p-2,就这么简单 ll inv(ll a,ll p) { return poww(a,p-2); } int main() { int n,k; cin>>n>>k; ll zero=0;//当前长度为k的字段有多少0,我们维护这个变量的意义是,当子段里有0,那么子段的乘积就为0 ll ans=0; ll temp=1; //temp维护区间内除0以外的数的乘积 //尺取法 for(int i=0;i<n;i++) { cin>>a[i]; if(!a[i]) zero++; //如果遇到0,则加一 else temp=temp*a[i]%mod; //否则乘以这个数 if(i>=k) { if(!a[i-k]) zero--; //如果k长度子段第一个元素前一个元素为0,说明我们的区间已经移动过去了 else temp=temp*inv(a[i-k],mod)%mod; //否则乘以它的逆元,因为0没有逆元 } if(i>=k-1&&!zero) ans=ans>temp?ans:temp;//如果zero=0,则说明该区间里面的数全部大于0,就可以和答案比较了 } printf("%lld",ans); return 0; }