传送门
两种方法:
1:逆元:
必须用逆元解决除回去不是原数字的尴尬局面。
eg:
如果0.5/3=x那么x*3还等于0.5吗?
显然不能,那么逆元就好了
代码:
#include<iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <functional>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <algorithm>
#define ll long long
#define mes(x,y) memset(x,y,sizeof(x))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
ll GCD(ll a, ll b) {//最大公约数
return b == 0 ? a : GCD(b, a % b);
}
ll Power(ll a, ll b, ll p) { //计算(a^b)%p;
ll ans = 1;
while (b) {
if (b & 1) //等价于b%2,判断b的奇偶性
ans = ans * a % p; //如果为奇数,证明该位为1,需要乘上a
a = a * a % p; //计算a^(2^i)
b >>= 1; //等价于b/=2;
}
return ans;
}
bool isprime(int num)
{
if (num == 2 || num == 3)
return true;
if (num % 6 != 1 && num % 6 != 5)
return false;
int t = sqrt((double)num);
for (int i = 5; i <= t; i += 6)
{
if (num % i == 0 || num % (i + 2) == 0)
return false;
}
return true;
}
const ll mod = 998244353;
const ll maxn = 1e9 + 10;
ll a[2000300];
int main() {
ll n, m, i, j, k;
string s;
while (cin >> n >> m) {
ll sum = 1;
ll maxv = 0;
mes(a, 0);
for (i = 0, j = 0; i < n; i++) {
cin >> a[i];
if (a[i] == 0)j = 0, sum = 1;
else {
sum = sum * a[i] % mod;
j++;
if (j >= m) {
//cout << i << ":" <<(ll)sum<<" "<< ((ll)sum % mod) << endl << endl;
maxv = max(maxv, sum);
sum = sum * Power(a[i - m + 1], mod - 2, mod) % mod;
}
}
}
cout << maxv << endl;
}
}
2:线段树:
这个采用了取巧的方法,不用除,只需找到那一段的乘积即可。
代码:
#include<iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <cmath>
#include <stack>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <functional>
#include <ctime>
#include <iomanip>
#include <sstream>
#include <algorithm>
#define ll long long
#define mes(x,y) memset(x,y,sizeof(x))
#define FAST_IO ios::sync_with_stdio(false);cin.tie(0);cout.tie(0)
using namespace std;
ll GCD(ll a, ll b) {//最大公约数
return b == 0 ? a : GCD(b, a % b);
}
ll Power(ll a, ll b, ll p) { //计算(a^b)%p;
ll ans = 1;
while (b) {
if (b & 1) //等价于b%2,判断b的奇偶性
ans = ans * a % p; //如果为奇数,证明该位为1,需要乘上a
a = a * a % p; //计算a^(2^i)
b >>= 1; //等价于b/=2;
}
return ans;
}
bool isprime(int num)
{
if (num == 2 || num == 3)
return true;
if (num % 6 != 1 && num % 6 != 5)
return false;
int t = sqrt((double)num);
for (int i = 5; i <= t; i += 6)
{
if (num % i == 0 || num % (i + 2) == 0)
return false;
}
return true;
}
const ll MOD = 998244353;
struct node
{
int l, r;
ll v;
}node[1500005];
void PushUp(int numb) // 向父节点更新数据;
{
node[numb].v = (node[numb << 1].v % MOD) * (node[numb << 1 | 1].v % MOD) % MOD;
}
void build(int l, int r, int numb) // 建树;
{
node[numb].l = l;
node[numb].r = r;
node[numb].v = 0;
if (l == r) return;
int mid = (l + r) >> 1;
build(l, mid, numb << 1);
build(mid + 1, r, numb << 1 | 1);
}
void Insert(int numb, int t, ll v) {
int l = node[numb].l, r = node[numb].r;
if (l == r && l == t) {
node[numb].v = v;
return;
}
int mid = (l + r) >> 1;
if (t > mid) Insert(numb << 1 | 1, t, v);
else if (t <= mid) Insert(numb << 1, t, v);
PushUp(numb);
}
ll query(int l, int r, int numb) {
if (node[numb].l == l && node[numb].r == r) {
return node[numb].v;
}
int mid = (node[numb].l + node[numb].r) >> 1;
if (l > mid) return query(l, r, numb << 1 | 1);
else if (r <= mid) return query(l, r, numb << 1);
else {
return (query(l, mid, numb << 1) * query(mid + 1, r, numb << 1 | 1)) % MOD;
}
}
int main() {
ll k, n, q, a, b;
while (cin >> n >> k) {
build(1, n, 1);
for (int i = 1; i <= n; i++) {
cin >> a;
Insert(1, i, a);
}
ll ans = 0;
for (int i = 1; i <= n - k + 1; i++) {
ll t = query(i, i + k - 1, 1);
ans = max(ans, t);
}
cout << ans << endl;
}
}