牛客小白赛4 C题
乘法逆元:
一个数a 乘上 b,在mod之后再还原成本来的数 a
这里就要用到乘法逆元,(a*b)%mod*inv(b,mod)==a
ll exgcd(ll a,ll b,ll &x,ll &y){ if(!b){ x=1;y=0; return a; } ll d=exgcd(b,a%b,x,y); ll tmp=x; x=y; y=tmp-a/b*y; return d; } ll inv(ll a,ll m){ ll x,y; ll d=exgcd(a,m,x,y); if(d==1){ return (x%m+m)%m; } return -1; }
题面:
给出一个长度为 n 的数列 a1,a2,…,an,求其长度为 k 的连续子段的乘积对 998244353 取模余数的最大值。
思路:
找到零的位置,两个零之间进行尺缩
因为有(a*b)%mod要还原成 a,所以要用到逆元,不然就是超时
#include<bits/stdc++.h> using namespace std; #define ll long long #define il inline #define it register int #define inf 0x3f3f3f3f #define lowbit(x) (x)&(-x) #define mem(a,b) memset(a,b,sizeof(a)) #define mod 998244353 ll exgcd(ll a,ll b,ll &x,ll &y){ if(!b){ x=1;y=0; return a; } ll d=exgcd(b,a%b,x,y); ll tmp=x; x=y; y=tmp-a/b*y; return d; } ll inv(ll a,ll m){ ll x,y; ll d=exgcd(a,m,x,y); if(d==1){ return (x%m+m)%m; } return -1; } const int maxn=2e5+10; int n,k,ling[maxn]; ll ans,a[maxn]; int main(){ scanf("%d%d",&n,&k); ans=1;ll maxx=0; it pos=1;ling[0]=0; for(it i=1;i<=n;i++){ scanf("%lld",&a[i]); if(a[i]==0){ling[pos++]=i;} } ling[pos++]=n+1; for(it i=1;i<pos;i++){ it c=ling[i]-ling[i-1]-1; if(c<k){continue;} else{ it kk=0;ans=1; for(it j=ling[i-1]+1;j<ling[i-1]+1+k;j++){ ans*=a[j];ans%=mod; } maxx=max(ans,maxx); for(it j=ling[i-1]+1+k;j<ling[i];j++){ ll sta=inv(a[j-k],mod); ans*=sta;ans%=mod;ans*=a[j];ans%=mod; maxx=max(ans,maxx); } } } printf("%lld\n",maxx); return 0; }
小白赛自闭了,就过了五题。c题过的人这么多,但我就是不会.jpg
inv=ksm(a,mod-2);