zoukankan      html  css  js  c++  java
  • 子段乘积(尺取、逆元)

    链接:https://ac.nowcoder.com/acm/contest/3005/C
    来源:牛客网

    题目描述

    给出一个长度为 n 的数列 a1,a2,…,an,求其长度为 k 的连续子段的乘积对 998244353 取模余数的最大值。

    输入描述:

    第一行两个整数n,k。
    第二行n个整数,a1,a2,…,an

    输出描述:

    输出一个整数,代表最大余数。

    输入

    5 3
    1 2 3 0 8

    输出

    6

    说明

    1∗2∗3 mod  998244353=6

    备注:

    1≤k≤n≤2∗105
    0ai<998244353

    本题可以使用线段树,也可以分治,还可以使用尺取法,维护当前区间中有几个0,同时维护不是0的数字的乘积,这种方法需要使用乘法逆元。

    思路:

    尺取法,l代表左端点,r代表右端点。

    l先不动,r往前扫描,如果成功扫到,有k个非0元素的子段就累成起来,最后把最左端的元素除了(用逆元),左端点往前移动,l++,再继续扫描。

    再未达到k个非零元素的子段前,如果遇到0,当前的区间重置 ,左端点直接到0的下一个位置继续扫描。

     1 #include <stdio.h>
     2 #include <string.h>
     3 #include <iostream>
     4 #include <string>
     5 #include <math.h>
     6 #include <algorithm>
     7 #include <vector>
     8 #include <stack>
     9 #include <queue>
    10 #include <set>
    11 #include <map>
    12 #include <sstream>
    13 const int INF=0x3f3f3f3f;
    14 typedef long long LL;
    15 //const int mod=1e9+7;
    16 const int mod=998244353;
    17 const int maxn=2e5+10;
    18 using namespace std;
    19 
    20 long long fpow(long long a, long long b)
    21 {
    22     if (a == 0) return 0;
    23     long long ans = 1;
    24     for (; b; b >>= 1, a = (a % mod * a% mod) % mod)
    25         if (b & 1) ans = (ans % mod * a % mod) % mod;
    26     return ans;
    27 }
    28 LL inv(LL a,LL mo)//用费马小定理求解a模mo的逆元
    29 {
    30     return fpow(a,mo-2)%mo;
    31 }
    32 
    33 LL a[maxn];
    34 
    35 int main()
    36 {
    37     #ifdef DEBUG
    38     freopen("sample.txt","r",stdin);
    39     #endif
    40     
    41     int n,k;
    42     scanf("%d %d",&n,&k);
    43     LL ans=0;
    44     for(int i=1;i<=n;i++)
    45         scanf("%d",&a[i]);
    46     LL sum=1;
    47     int l=1;//尺取法
    48     int r=1;
    49     while(r<=n)
    50     {
    51         if(a[r])
    52         {
    53             sum=sum*a[r]%mod;
    54             if(r-l+1==k)//达到k子段
    55             {
    56                 ans=max(ans,sum);//更新最大值 
    57                 sum=sum*inv(a[l],mod)%mod;//除掉左端点(乘逆元) 
    58                 l++;
    59             }
    60         }
    61         else//如果遇到0,重置 
    62         {
    63             l=r+1;// 左端点直接到0的下一个位置
    64             sum=1;//sum重置为1
    65         }
    66         r++;
    67     }
    68     printf("%lld
    ",ans);
    69     
    70     return 0;
    71 }

    -

  • 相关阅读:
    link和@import的区别
    行内元素、块状元素和行内块元素
    content-box与border-box区别
    实现浏览器内多个标签页之间的通信
    cookie、 sessionStorage 、localStorage之间的区别和使用
    让浏览器识别HTML5规范中的新标签
    HTML5新增及移除的元素
    摇一摇
    WebViewJavascriptBridge
    使用TFHpple解析html
  • 原文地址:https://www.cnblogs.com/jiamian/p/12301139.html
Copyright © 2011-2022 走看看