牛客小白赛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);

 

posted @ 2020-02-11 18:50  ouluy  阅读(109)  评论(0编辑  收藏  举报