2020牛客寒假算法基础集训营4 C 子段乘积
时间:2022-07-26
本文章向大家介绍2020牛客寒假算法基础集训营4 C 子段乘积,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
给出一个长度为 n的数列
a1,a2,a3,a4,…,an
求其长度为 k 的连续子段的乘积对 998244353 取模余数的最大值。
数据范围:1<=k<=2e5,0<=ai<998244353
法一:由于它限制了连续子段所包含的元素数目,很明显只有n-k+1
段,枚举就好,但是枚举的时候应该是要用到乘法逆元,因为你要乘下一个数ai+1, 除上一个被你踢出的元素ai+1-k ,同时你得考虑到这个数是零的情况,需要用到乘法逆元
乘法逆元,一般用于求a/b%p的值(p 通常为质数),是解决模意义下a/b的有效方法手段,在这里比方说要求a/b%p,那么就是a*inv(b),inv(b)表示b的逆元(模p意义下),inv(b)*b%p=1。
求逆元这里用个简单方法 首先引入费马小定理,两个数a,p如果p是质数,gcd(a,p)=1即a不是p的倍数,那么有a^p-1%p=1 换句话说就是a的p-1次方与1同余于p,那么a的逆元不就是a^(p-2)吗?快速幂一次即可求出
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rg register ll
#define mod 998244353
ll n,k,ans,a[200005];
inline ll qpow(ll a,ll b)
{
ll res=1;
while(b)
{
if(b&1)res=res*a%mod;
a=a*a%mod;
b>>=1;
}
return res;
}
int main()
{
cin>>n>>k;
ll cnt=0,res=1;
for(rg i=1;i<=n;i++)cin>>a[i];
for(rg i=1;i<=n;i++)
{
if(!a[i]) {cnt=0,res=1;}
else
{
if(cnt<k)//1~k-1的时候执行这个语句
{
res=res*a[i]%mod;
cnt++;
if(cnt==k)ans=max(ans,res);
}
else//t一个进一个
{
res=res*qpow(a[i-k],mod-2)%mod;
res=res*a[i]%mod;
ans=max(ans,res);
}
}
}
cout<<ans<<endl;
while(1)getchar();
return 0;
}
法二:分治or线段树
线段树和分治一个思想,都是优雅的暴力,比方说我要求1~n的乘积我怎么求?我先求1~n/2的,再求n/2+1~n的,这样就能保证logn就可得到结果,那么我们无非最多进行n-k+1次查询,时间复杂度不过nlogn,可过!
自己写的线段树,可能常数有点大
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define rg register ll
#define mod 998244353
ll n,k,a[200005],sum[200005*4];
inline void push_up(ll rt)
{
sum[rt]=(sum[2*rt]%mod)*(sum[2*rt+1]%mod)%mod;
}
inline void build(ll l,ll r,ll rt)
{
if(l==r){sum[rt]=a[l];return ;}
ll m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
push_up(rt);
}
inline ll query(ll l,ll r,ll rt,ll a,ll b)
{
ll res=1;
if(a<=l&&b>=r){return sum[rt];}
ll m=(l+r)>>1;
if(m>=a) res=(res%mod)*(query(l,m,rt<<1,a,b)%mod)%mod;
if(m+1<=b) res=(res%mod)*(query(m+1,r,rt<<1|1,a,b)%mod)%mod;
return res;
}
int main()
{
cin>>n>>k;
for(rg i=1;i<=n;i++)cin>>a[i];
build(1,n,1);
ll ans=0;
for(rg i=1;i+k-1<=n;i++)
{
ans=max(ans,query(1,n,1,i,i+k-1));
}
cout<<ans<<endl;
while(1)getchar();
return 0;
}
- 深度|Python股票数据分析
- HDU 2438 Turn the corner(三分查找)
- UVAlive 3708 Graveyard(最优化问题)
- HDU 1754 I Hate It(线段树之单点更新,区间最值)
- Selenium2+python自动化19-单选和复选框
- Uva 11300 Spreading the Wealth(递推,中位数)
- Uva 11729 Commando War (简单贪心)
- UVA 11292 Dragon of Loowater(简单贪心)
- Codeforces Beta Round #2 A,B,C
- 牛顿迭代法(Newton's Method)
- 最长递减子序列(nlogn)(个人模版)
- Selenium2+python自动化26-js处理内嵌div滚动条
- Selenium2+python自动化25-js处理日历控件
- 转负二进制(个人模版)
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 浅析php如何实现爬取数据原理
- Python 存取npy格式数据实例
- 微信支付之JSAPI公众号支付详解
- 浅谈keras中的batch_dot,dot方法和TensorFlow的matmul
- Python代码执行时间测量模块timeit用法解析
- Laravel框架实现简单的学生信息管理平台案例【附源码下载】
- numpy 矩阵形状调整:拉伸、变成一位数组的实例
- 使用Nibabel库对nii格式图像的读写操作
- ThinkPHP like模糊查询,like多匹配查询,between查询,in查询,一般查询书写方法
- 使用SimpleITK读取和保存NIfTI/DICOM文件实例
- php中上传文件的的解决方案
- python 实现两个npy档案合并
- PHP使用函数用法详解
- 读取nii或nii.gz文件中的信息即输出图像操作
- PHP实现SMTP邮件的发送实例