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;
}
- 另类大数据:中国有嘻哈的rapper们都在唱些什么?
- jquery属性值选择器
- sqlserver 2000/2005 Ambiguous column error错误解决办法
- jquery 层级选择器
- Twitter发布基于组件的轻量级JavaScript框架——Flight
- jquery的基本选择器
- WordPress 路径相关函数总结(一):站点路径相关函数
- 修复Visual Studio 2010 SP1的Toolbox导致的VS不可用
- 破解Excel 密码保护
- 配置Subversion
- WordPress 路径相关函数总结(二):主题路径相关函数
- ASP.NET 2.0 中 Web 事件
- Visual Studio 必备可视化插件推荐
- WordPress 路径相关函数总结(一):站点路径相关函数
- 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 数组属性和方法
- 浙大版《C语言程序设计(第3版)》题目集 练习7-10 查找指定字符
- 浙大版《C语言程序设计(第3版)》题目集 练习7-11 字符串逆序
- 浙大版《C语言程序设计(第3版)》题目集 习题7-1 选择法排序
- 浙大版《C语言程序设计(第3版)》题目集 习题7-2 求一批整数中出现最多的个位数字
- 浙大版《C语言程序设计(第3版)》题目集 习题7-3 判断上三角矩阵
- 浙大版《C语言程序设计(第3版)》题目集 习题7-4 求矩阵各行元素之和
- 浙大版《C语言程序设计(第3版)》题目集 习题7-6 统计大写辅音字母
- 浙大版《C语言程序设计(第3版)》题目集 习题7-7 字符串替换
- 浙大版《C语言程序设计(第3版)》题目集 习题8-10 输出学生成绩
- 浙大版《C语言程序设计(第3版)》题目集 习题9-1 时间换算
- 浙大版《C语言程序设计(第3版)》题目集 习题9-3 平面向量加法
- 浙大版《C语言程序设计(第3版)》题目集 习题9-4 查找书籍
- 浙大版《C语言程序设计(第3版)》题目集 习题9-5 通讯录排序
- 浙大版《C语言程序设计(第3版)》题目集 习题7-5 找鞍点
- 浙大版《C语言程序设计(第3版)》题目集 练习5-1 求m到n之和