2020牛客寒假算法基础集训营4C题
嘻嘻我又来啦,最近补题补的有点点勤=-=
传送门
C题让我彻彻底底的明白了。。费马,您是个多么伟大的人啊(膜拜)
赛后补题参考的是zz的代码啦,不过他没有发博客,我无法转载进来
嘻嘻不过他是不会介意的=-=(ps:我最近看他的好几道题都是他都是用双指针来做的=-=,关键是我这木鱼脑袋还没有掌握到精髓qaq)
这道题他也是用双指针来写的(想来想去,我是不是帮他写了一篇博客=-=)
题目的大概意思就是说呢又是给你一个序列,让你找出一个长度为k子序列乘积最大。
我首先看到这道题脑海里面又涌现了dp(中毒了啊),跟dp最大子序列之和以及最大子序列之积差不多呀,但是在写的过程中不知道k怎么用,而且题目描述的数值也没有小于零的情况=-=(我就很迷,还是太年轻了)
双指针这么用:l是left,r是right,l和r锁定一个不包含0的长度为k的子序列,求这个乘积(记得取模),然后维护最大的乘积,之后除以最前面的一个数,慢慢的求后面的乘积(这里用乘法逆元,我栽在这里了),因为取模之后的数和原来的乘积不一样呀(而且我下午用双指针的时候,傻乎乎的每次维护完最大的答案,就把存放乘积的变量更新为1,重新求一次,不超时才怪!!)
看过zz使用双指针的代码=-=他喜欢这么用,做完某次操作,不知是何种原因退出了while循环,于是下面来一个判断,咦,不满足要求了,要退出了,于是来一个if,break掉,后面的代码跟不符合要求的子序列就无关了,于是可以放心大胆的无条件做操作(就是这里的精髓我没有掌握=-=)
乘法逆元偶要单独写出来!!!(警示!!!)
ll power(ll a, ll b)
{
ll sum = 1;
while (b)
{
if (b & 1)
{
sum = sum * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return sum;
}
好啦~又到了上代码的环节啦嘻嘻
开心
#include <bits/stdc++.h>
using namespace std;
#define mst(a, n) memset(a, n, sizeof(a))
typedef long long ll;
const int N = 2e5 + 10;
const ll mod = 998244353;
int n, k;
ll a[N];
ll ans;
ll power(ll a, ll b)
{
ll sum = 1;
while (b)
{
if (b & 1)
{
sum = sum * a % mod;
}
a = a * a % mod;
b >>= 1;
}
return sum;
}
int main()
{
cin >> n >> k;
for (int i = 1; i <= n; i++)
{
cin >> a[i];
}
int l = 1, r = 1;
ll temp = 1;
while (l <= n)
{
while (r <= n && r - l < k)
{
while (!a[r] && r <= n)
{
temp = 1;
l = r + 1;
r = l;
}
temp = temp * a[r] % mod;
r++;
}
if (r - l < k)
{
break;
}
ans = max(ans, temp);
temp = temp * power(a[l++], mod - 2) % mod;
}
cout << ans << endl;
return 0;
}
双指针我一定要熟练!!!一定
最后发表感言:感谢zz!!!(虽然他不知情=-=)
到时间我去洗澡了=-=