k连续子段乘积

https://ac.nowcoder.com/acm/contest/3005/C

题意:求长度为k的连续子段乘积。

解法1逆元:前缀乘积(不含0),记录前缀0的个数,并求不含0的长度为k的连续子段乘积中取最大的。

注意0没有逆元,所以在考虑递推方法时0要特殊处理。

#include <bits/stdc++.h>
#define ME(x , y) memset(x , y , sizeof(x))
#define SC scanf
#define rep(i ,j , n) for(int i = j ; i < n ; i ++)
#define red(i , n , j) for(int i = n-1 ; i >= j ; i--)
#define INF  0x3f3f3f3f
#define mod 998244353
#define PI acos(-1)
#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
using namespace std;
typedef long long ll ;
const int MX = 1e5+9;
ll pre[200009];
ll a[200009];
int cnt0[200009];//前缀0的个数
ll quickpow(ll a , ll b){
    ll ans = 1 ;
    while(b){
        if(b&1) ans = ans%mod * a % mod;
        b >>= 1 ;
        a = a%mod * a %mod;
    }
    return ans;
}
 int main() {
 
    int n , k ;
    cin >> n >> k;
    pre[0] = 1   ;
    rep(i , 1 , n+1){
        scanf("%lld" , &a[i]);
    }
    rep(i , 1 , n+1){
        if(a[i] == 0){
            pre[i] = pre[i-1];
            cnt0[i] = cnt0[i-1]+1;
        }else{
            pre[i] = (pre[i-1]*a[i])%mod;
            cnt0[i] = cnt0[i-1];
        }
    }
 
    ll ans = 0;
    rep(i , k , n+1){
        int j = i-k+1;
        if(cnt0[i] == cnt0[j-1]){//长度k连续子段不含0
            ll temp = pre[i]*quickpow(pre[j-1] , mod-2)%mod;
            ans = max(ans , temp);
        }
    }
    cout << ans << endl;
    return 0 ;
 }

 解法2:线段树O(nlogn)求每一段连续k乘积

#include <bits/stdc++.h>
#define ME(x , y) memset(x , y , sizeof(x))
#define SC scanf
#define rep(i ,j , n) for(int i = j ; i < n ; i ++)
#define red(i , n , j) for(int i = n-1 ; i >= j ; i--)
#define INF  0x3f3f3f3f
#define mod 998244353
#define PI acos(-1)
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
using namespace std;
typedef long long ll ;
const int maxn = 2e5+9;
ll val[maxn<<2];

void build(int l , int r , int root){
    if(l == r){
        scanf("%lld" , &val[root]);
        return ;
    }
    int mid = (l + r)>>1;
    build(lson);
    build(rson);
    val[root] = val[root<<1]%mod * val[root<<1|1]%mod ;
}

ll query(int l , int r , int root , int L , int R){
    if(l >= L && r <= R){
        return val[root]%mod;
    }
    ll sum = 1 ;
    int mid = (l+r) >> 1;
    if(L <= mid)
        sum = sum%mod * query(lson , L , R)%mod;
    if(mid < R)
        sum = sum%mod * query(rson , L , R)%mod;
    return sum%mod ;
}

int main()
{
    int n , k ;
    cin >> n >> k;
    build(1 , n , 1);
    ll ans = 0 ;
    rep(i , k , n+1){
        ans = max(ans , query(1 , n , 1 , i-k+1 , i));
    }
    cout << ans << endl;
    return 0;
}

 

posted @ 2020-02-12 00:12  无名菜鸟1  阅读(236)  评论(0编辑  收藏  举报